diff --git a/fuzzers/tint_ast_clone_fuzzer.cc b/fuzzers/tint_ast_clone_fuzzer.cc index f773aa4865..fdb83c17aa 100644 --- a/fuzzers/tint_ast_clone_fuzzer.cc +++ b/fuzzers/tint_ast_clone_fuzzer.cc @@ -77,7 +77,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { for (auto* src_node : src.ASTNodes().Objects()) { src_nodes.emplace(src_node); } - std::unordered_set src_types; + std::unordered_set src_types; for (auto* src_type : src.Types()) { src_types.emplace(src_type); } diff --git a/src/BUILD.gn b/src/BUILD.gn index 191428091f..2a940b6c56 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -284,8 +284,12 @@ libtint_source_set("libtint_core_all_src") { "ast/access_control.h", "ast/access_decoration.cc", "ast/access_decoration.h", + "ast/alias.cc", + "ast/alias.h", "ast/array_accessor_expression.cc", "ast/array_accessor_expression.h", + "ast/array.cc", + "ast/array.h", "ast/assignment_statement.cc", "ast/assignment_statement.h", "ast/binary_expression.cc", @@ -298,12 +302,14 @@ libtint_source_set("libtint_core_all_src") { "ast/block_statement.h", "ast/bool_literal.cc", "ast/bool_literal.h", + "ast/bool.cc", + "ast/bool.h", "ast/break_statement.cc", "ast/break_statement.h", - "ast/builtin.cc", - "ast/builtin.h", "ast/builtin_decoration.cc", "ast/builtin_decoration.h", + "ast/builtin.cc", + "ast/builtin.h", "ast/call_expression.cc", "ast/call_expression.h", "ast/call_statement.cc", @@ -318,12 +324,16 @@ libtint_source_set("libtint_core_all_src") { "ast/continue_statement.h", "ast/decoration.cc", "ast/decoration.h", + "ast/depth_texture.cc", + "ast/depth_texture.h", "ast/discard_statement.cc", "ast/discard_statement.h", "ast/else_statement.cc", "ast/else_statement.h", "ast/expression.cc", "ast/expression.h", + "ast/f32.cc", + "ast/f32.h", "ast/fallthrough_statement.cc", "ast/fallthrough_statement.h", "ast/float_literal.cc", @@ -332,6 +342,8 @@ libtint_source_set("libtint_core_all_src") { "ast/function.h", "ast/group_decoration.cc", "ast/group_decoration.h", + "ast/i32.cc", + "ast/i32.h", "ast/identifier_expression.cc", "ast/identifier_expression.h", "ast/if_statement.cc", @@ -346,16 +358,26 @@ libtint_source_set("libtint_core_all_src") { "ast/location_decoration.h", "ast/loop_statement.cc", "ast/loop_statement.h", + "ast/matrix.cc", + "ast/matrix.h", "ast/member_accessor_expression.cc", "ast/member_accessor_expression.h", "ast/module.cc", "ast/module.h", + "ast/multisampled_texture.cc", + "ast/multisampled_texture.h", "ast/node.cc", "ast/node.h", "ast/pipeline_stage.cc", "ast/pipeline_stage.h", + "ast/pointer.cc", + "ast/pointer.h", "ast/return_statement.cc", "ast/return_statement.h", + "ast/sampled_texture.cc", + "ast/sampled_texture.h", + "ast/sampler.cc", + "ast/sampler.h", "ast/scalar_constructor_expression.cc", "ast/scalar_constructor_expression.h", "ast/sint_literal.cc", @@ -366,34 +388,46 @@ libtint_source_set("libtint_core_all_src") { "ast/statement.h", "ast/storage_class.cc", "ast/storage_class.h", + "ast/storage_texture.cc", + "ast/storage_texture.h", "ast/stride_decoration.cc", "ast/stride_decoration.h", - "ast/struct.cc", - "ast/struct.h", "ast/struct_block_decoration.cc", "ast/struct_block_decoration.h", - "ast/struct_member.cc", - "ast/struct_member.h", "ast/struct_member_align_decoration.cc", "ast/struct_member_align_decoration.h", "ast/struct_member_offset_decoration.cc", "ast/struct_member_offset_decoration.h", "ast/struct_member_size_decoration.cc", "ast/struct_member_size_decoration.h", + "ast/struct_member.cc", + "ast/struct_member.h", + "ast/struct.cc", + "ast/struct.h", "ast/switch_statement.cc", "ast/switch_statement.h", + "ast/texture.cc", + "ast/texture.h", "ast/type_constructor_expression.cc", "ast/type_constructor_expression.h", + "ast/ast_type.cc", # TODO(bclayton) - rename to type.cc + "ast/type.h", + "ast/u32.cc", + "ast/u32.h", "ast/uint_literal.cc", "ast/uint_literal.h", - "ast/unary_op.cc", - "ast/unary_op.h", "ast/unary_op_expression.cc", "ast/unary_op_expression.h", - "ast/variable.cc", - "ast/variable.h", + "ast/unary_op.cc", + "ast/unary_op.h", "ast/variable_decl_statement.cc", "ast/variable_decl_statement.h", + "ast/variable.cc", + "ast/variable.h", + "ast/vector.cc", + "ast/vector.h", + "ast/void.cc", + "ast/void.h", "ast/workgroup_decoration.cc", "ast/workgroup_decoration.h", "block_allocator.h", @@ -419,12 +453,12 @@ libtint_source_set("libtint_core_all_src") { "inspector/scalar.h", "intrinsic_table.cc", "intrinsic_table.h", - "program.cc", - "program.h", "program_builder.cc", "program_builder.h", "program_id.cc", "program_id.h", + "program.cc", + "program.h", "reader/reader.cc", "reader/reader.h", "resolver/resolver.cc", @@ -474,10 +508,10 @@ libtint_source_set("libtint_core_all_src") { "sem/void_type.h", "source.cc", "source.h", - "symbol.cc", - "symbol.h", "symbol_table.cc", "symbol_table.h", + "symbol.cc", + "symbol.h", "traits.h", "transform/binding_point.h", "transform/binding_remapper.cc", @@ -510,10 +544,10 @@ libtint_source_set("libtint_core_all_src") { "writer/append_vector.h", "writer/float_to_string.cc", "writer/float_to_string.h", - "writer/text.cc", - "writer/text.h", "writer/text_generator.cc", "writer/text_generator.h", + "writer/text.cc", + "writer/text.h", "writer/writer.cc", "writer/writer.h", ] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cac6fbeb1d..9e6de7bffb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,8 +42,12 @@ set(TINT_LIB_SRCS ast/access_control.h ast/access_decoration.cc ast/access_decoration.h + ast/alias.cc + ast/alias.h ast/array_accessor_expression.cc ast/array_accessor_expression.h + ast/array.cc + ast/array.h ast/assignment_statement.cc ast/assignment_statement.h ast/binary_expression.cc @@ -56,6 +60,8 @@ set(TINT_LIB_SRCS ast/block_statement.h ast/bool_literal.cc ast/bool_literal.h + ast/bool.cc + ast/bool.h ast/break_statement.cc ast/break_statement.h ast/builtin_decoration.cc @@ -76,12 +82,16 @@ set(TINT_LIB_SRCS ast/continue_statement.h ast/decoration.cc ast/decoration.h + ast/depth_texture.cc + ast/depth_texture.h ast/discard_statement.cc ast/discard_statement.h ast/else_statement.cc ast/else_statement.h ast/expression.cc ast/expression.h + ast/f32.cc + ast/f32.h ast/fallthrough_statement.cc ast/fallthrough_statement.h ast/float_literal.cc @@ -90,6 +100,8 @@ set(TINT_LIB_SRCS ast/function.h ast/group_decoration.cc ast/group_decoration.h + ast/i32.cc + ast/i32.h ast/identifier_expression.cc ast/identifier_expression.h ast/if_statement.cc @@ -104,16 +116,26 @@ set(TINT_LIB_SRCS ast/location_decoration.h ast/loop_statement.cc ast/loop_statement.h + ast/matrix.cc + ast/matrix.h ast/member_accessor_expression.cc ast/member_accessor_expression.h ast/module.cc ast/module.h + ast/multisampled_texture.cc + ast/multisampled_texture.h ast/node.cc ast/node.h ast/pipeline_stage.cc ast/pipeline_stage.h + ast/pointer.cc + ast/pointer.h ast/return_statement.cc ast/return_statement.h + ast/sampled_texture.cc + ast/sampled_texture.h + ast/sampler.cc + ast/sampler.h ast/scalar_constructor_expression.cc ast/scalar_constructor_expression.h ast/sint_literal.cc @@ -124,34 +146,46 @@ set(TINT_LIB_SRCS ast/statement.h ast/storage_class.cc ast/storage_class.h + ast/storage_texture.cc + ast/storage_texture.h ast/stride_decoration.cc ast/stride_decoration.h - ast/struct.cc - ast/struct.h ast/struct_block_decoration.cc ast/struct_block_decoration.h - ast/struct_member.cc - ast/struct_member.h ast/struct_member_align_decoration.cc ast/struct_member_align_decoration.h ast/struct_member_offset_decoration.cc ast/struct_member_offset_decoration.h ast/struct_member_size_decoration.cc ast/struct_member_size_decoration.h + ast/struct_member.cc + ast/struct_member.h + ast/struct.cc + ast/struct.h ast/switch_statement.cc ast/switch_statement.h + ast/texture.cc + ast/texture.h ast/type_constructor_expression.cc ast/type_constructor_expression.h + ast/ast_type.cc # TODO(bclayton) - rename to type.cc + ast/type.h + ast/u32.cc + ast/u32.h ast/uint_literal.cc ast/uint_literal.h - ast/unary_op.cc - ast/unary_op.h ast/unary_op_expression.cc ast/unary_op_expression.h - ast/variable.cc - ast/variable.h + ast/unary_op.cc + ast/unary_op.h ast/variable_decl_statement.cc ast/variable_decl_statement.h + ast/variable.cc + ast/variable.h + ast/vector.cc + ast/vector.h + ast/void.cc + ast/void.h ast/workgroup_decoration.cc ast/workgroup_decoration.h block_allocator.h @@ -163,8 +197,6 @@ set(TINT_LIB_SRCS debug.h demangler.cc demangler.h - intrinsic_table.cc - intrinsic_table.h diagnostic/diagnostic.cc diagnostic/diagnostic.h diagnostic/formatter.cc @@ -177,6 +209,8 @@ set(TINT_LIB_SRCS inspector/inspector.h inspector/scalar.cc inspector/scalar.h + intrinsic_table.cc + intrinsic_table.h program_builder.cc program_builder.h program_id.cc @@ -188,32 +222,32 @@ set(TINT_LIB_SRCS resolver/resolver.cc resolver/resolver.h scope_stack.h - sem/array.h - sem/call.h - sem/call_target.h - sem/expression.h - sem/info.h - sem/intrinsic.h - sem/node.h sem/array.cc - sem/call.cc + sem/array.h sem/call_target.cc + sem/call_target.h + sem/call.cc + sem/call.h sem/expression.cc - sem/member_accessor_expression.cc + sem/expression.h sem/function.cc sem/info.cc + sem/info.h sem/intrinsic.cc + sem/intrinsic.h + sem/member_accessor_expression.cc sem/node.cc + sem/node.h sem/statement.cc sem/struct.cc - sem/variable.cc sem/type_mappings.h + sem/variable.cc source.cc source.h - symbol.cc - symbol.h symbol_table.cc symbol_table.h + symbol.cc + symbol.h traits.h transform/binding_point.h transform/binding_remapper.cc @@ -288,10 +322,10 @@ set(TINT_LIB_SRCS writer/append_vector.h writer/float_to_string.cc writer/float_to_string.h - writer/text.cc - writer/text.h writer/text_generator.cc writer/text_generator.h + writer/text.cc + writer/text.h writer/writer.cc writer/writer.h ) @@ -418,14 +452,18 @@ endif() if(${TINT_BUILD_TESTS}) set(TINT_TEST_SRCS + ast/access_control_test.cc ast/access_decoration_test.cc + ast/alias_test.cc ast/array_accessor_expression_test.cc + ast/array_test.cc ast/assignment_statement_test.cc ast/binary_expression_test.cc ast/binding_decoration_test.cc ast/bitcast_expression_test.cc ast/block_statement_test.cc ast/bool_literal_test.cc + ast/bool_test.cc ast/break_statement_test.cc ast/builtin_decoration_test.cc ast/call_expression_test.cc @@ -433,12 +471,15 @@ if(${TINT_BUILD_TESTS}) ast/case_statement_test.cc ast/constant_id_decoration_test.cc ast/continue_statement_test.cc + ast/depth_texture_test.cc ast/discard_statement_test.cc ast/else_statement_test.cc + ast/f32_test.cc ast/fallthrough_statement_test.cc ast/float_literal_test.cc ast/function_test.cc ast/group_decoration_test.cc + ast/i32_test.cc ast/identifier_expression_test.cc ast/if_statement_test.cc ast/int_literal_test.cc @@ -446,13 +487,19 @@ if(${TINT_BUILD_TESTS}) ast/intrinsic_texture_helper_test.h ast/location_decoration_test.cc ast/loop_statement_test.cc + ast/matrix_test.cc ast/member_accessor_expression_test.cc ast/module_clone_test.cc ast/module_test.cc + ast/multisampled_texture_test.cc + ast/pointer_test.cc ast/return_statement_test.cc + ast/sampled_texture_test.cc + ast/sampler_test.cc ast/scalar_constructor_expression_test.cc ast/sint_literal_test.cc ast/stage_decoration_test.cc + ast/storage_texture_test.cc ast/stride_decoration_test.cc ast/struct_member_align_decoration_test.cc ast/struct_member_offset_decoration_test.cc @@ -461,11 +508,14 @@ if(${TINT_BUILD_TESTS}) ast/struct_test.cc ast/switch_statement_test.cc ast/test_helper.h + ast/texture_test.cc ast/type_constructor_expression_test.cc + ast/u32_test.cc ast/uint_literal_test.cc ast/unary_op_expression_test.cc ast/variable_decl_statement_test.cc ast/variable_test.cc + ast/vector_test.cc ast/workgroup_decoration_test.cc block_allocator_test.cc castable_test.cc @@ -501,7 +551,6 @@ if(${TINT_BUILD_TESTS}) sem/intrinsic_test.cc symbol_table_test.cc symbol_test.cc - traits_test.cc test_main.cc sem/access_control_type_test.cc sem/alias_type_test.cc diff --git a/src/ast/access_control.cc b/src/ast/access_control.cc index 9a70a6435d..0c1c1d3449 100644 --- a/src/ast/access_control.cc +++ b/src/ast/access_control.cc @@ -14,10 +14,68 @@ #include "src/ast/access_control.h" +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::AccessControl); + namespace tint { namespace ast { -std::ostream& operator<<(std::ostream& out, AccessControl access) { +AccessControl::AccessControl(ProgramID program_id, + const Source& source, + Access access, + Type* subtype) + : Base(program_id, source), access_(access), subtype_(subtype) { + TINT_ASSERT(subtype_); + TINT_ASSERT(!subtype_->Is()); +} + +AccessControl::AccessControl(AccessControl&&) = default; + +AccessControl::~AccessControl() = default; + +std::string AccessControl::type_name() const { + std::string name = "__access_control_"; + switch (access_) { + case ast::AccessControl::kReadOnly: + name += "read_only"; + break; + case ast::AccessControl::kWriteOnly: + name += "write_only"; + break; + case ast::AccessControl::kReadWrite: + name += "read_write"; + break; + } + return name + subtype_->type_name(); +} + +std::string AccessControl::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + out << "[[access("; + switch (access_) { + case ast::AccessControl::kReadOnly: + out << "read"; + break; + case ast::AccessControl::kWriteOnly: + out << "write"; + break; + case ast::AccessControl::kReadWrite: + out << "read_write"; + break; + } + out << ")]] " << subtype_->FriendlyName(symbols); + return out.str(); +} + +AccessControl* AccessControl::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, access_, ty); +} + +std::ostream& operator<<(std::ostream& out, AccessControl::Access access) { switch (access) { case ast::AccessControl::kReadOnly: { out << "read_only"; diff --git a/src/ast/access_control.h b/src/ast/access_control.h index 4539cd1f7b..106b31e62e 100644 --- a/src/ast/access_control.h +++ b/src/ast/access_control.h @@ -16,24 +16,73 @@ #define SRC_AST_ACCESS_CONTROL_H_ #include +#include + +#include "src/ast/type.h" namespace tint { namespace ast { -/// 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 AccessControl : public Castable { + public: + /// The access control settings + enum Access { + /// Read only + kReadOnly = 0, + /// Write only + kWriteOnly, + /// Read write + kReadWrite + }; + + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param access the access control setting + /// @param subtype the access controlled type + AccessControl(ProgramID program_id, + const Source& source, + Access access, + Type* subtype); + /// Move constructor + AccessControl(AccessControl&&); + ~AccessControl() override; + + /// @returns true if the access control is read only + bool IsReadOnly() const { return access_ == Access::kReadOnly; } + /// @returns true if the access control is write only + bool IsWriteOnly() const { return access_ == Access::kWriteOnly; } + /// @returns true if the access control is read/write + bool IsReadWrite() const { return access_ == Access::kReadWrite; } + + /// @returns the access control value + Access access_control() const { return access_; } + /// @returns the subtype type + Type* type() const { return subtype_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + AccessControl* Clone(CloneContext* ctx) const override; + + private: + Access const access_; + Type* const subtype_; }; /// @param out the std::ostream to write to /// @param access the AccessControl /// @return the std::ostream so calls can be chained -std::ostream& operator<<(std::ostream& out, AccessControl access); +std::ostream& operator<<(std::ostream& out, AccessControl::Access access); } // namespace ast } // namespace tint diff --git a/src/ast/access_control_test.cc b/src/ast/access_control_test.cc new file mode 100644 index 0000000000..c03d833d7c --- /dev/null +++ b/src/ast/access_control_test.cc @@ -0,0 +1,112 @@ +// 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/access_control.h" + +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstAccessControlTest = TestHelper; + +TEST_F(AstAccessControlTest, Create) { + auto* u32 = create(); + auto* a = create(AccessControl::kReadWrite, u32); + EXPECT_TRUE(a->IsReadWrite()); + EXPECT_EQ(a->type(), u32); +} + +TEST_F(AstAccessControlTest, Is) { + auto* i32 = create(); + Type* ty = create(AccessControl::kReadOnly, i32); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstAccessControlTest, AccessRead) { + auto* i32 = create(); + auto* ac = create(AccessControl::kReadOnly, i32); + EXPECT_TRUE(ac->IsReadOnly()); + EXPECT_FALSE(ac->IsWriteOnly()); + EXPECT_FALSE(ac->IsReadWrite()); + + EXPECT_EQ(ac->type_name(), "__access_control_read_only__i32"); +} + +TEST_F(AstAccessControlTest, AccessWrite) { + auto* i32 = create(); + auto* ac = create(AccessControl::kWriteOnly, i32); + EXPECT_FALSE(ac->IsReadOnly()); + EXPECT_TRUE(ac->IsWriteOnly()); + EXPECT_FALSE(ac->IsReadWrite()); + + EXPECT_EQ(ac->type_name(), "__access_control_write_only__i32"); +} + +TEST_F(AstAccessControlTest, AccessReadWrite) { + auto* i32 = create(); + auto* ac = create(AccessControl::kReadWrite, i32); + EXPECT_FALSE(ac->IsReadOnly()); + EXPECT_FALSE(ac->IsWriteOnly()); + EXPECT_TRUE(ac->IsReadWrite()); + + EXPECT_EQ(ac->type_name(), "__access_control_read_write__i32"); +} + +TEST_F(AstAccessControlTest, FriendlyNameReadOnly) { + auto* i32 = create(); + auto* ac = create(AccessControl::kReadOnly, i32); + EXPECT_EQ(ac->FriendlyName(Symbols()), "[[access(read)]] i32"); +} + +TEST_F(AstAccessControlTest, FriendlyNameWriteOnly) { + auto* i32 = create(); + auto* ac = create(AccessControl::kWriteOnly, i32); + EXPECT_EQ(ac->FriendlyName(Symbols()), "[[access(write)]] i32"); +} + +TEST_F(AstAccessControlTest, FriendlyNameReadWrite) { + auto* i32 = create(); + auto* ac = create(AccessControl::kReadWrite, i32); + EXPECT_EQ(ac->FriendlyName(Symbols()), "[[access(read_write)]] i32"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/access_decoration.cc b/src/ast/access_decoration.cc index ad5be5bebe..e00ace6c43 100644 --- a/src/ast/access_decoration.cc +++ b/src/ast/access_decoration.cc @@ -23,7 +23,7 @@ namespace ast { AccessDecoration::AccessDecoration(ProgramID program_id, const Source& source, - AccessControl val) + AccessControl::Access val) : Base(program_id, source), value_(val) {} AccessDecoration::~AccessDecoration() = default; diff --git a/src/ast/access_decoration.h b/src/ast/access_decoration.h index 0ad41bf700..894bb69882 100644 --- a/src/ast/access_decoration.h +++ b/src/ast/access_decoration.h @@ -30,11 +30,11 @@ class AccessDecoration : public Castable { /// @param value the access value AccessDecoration(ProgramID program_id, const Source& source, - AccessControl value); + AccessControl::Access value); ~AccessDecoration() override; /// @returns the access control value - AccessControl value() const { return value_; } + AccessControl::Access value() const { return value_; } /// Outputs the decoration to the given stream /// @param sem the semantic info for the program @@ -51,7 +51,7 @@ class AccessDecoration : public Castable { AccessDecoration* Clone(CloneContext* ctx) const override; private: - AccessControl const value_; + AccessControl::Access const value_; }; } // namespace ast diff --git a/src/ast/alias.cc b/src/ast/alias.cc new file mode 100644 index 0000000000..80e595780c --- /dev/null +++ b/src/ast/alias.cc @@ -0,0 +1,53 @@ +// 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/alias.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Alias); + +namespace tint { +namespace ast { + +Alias::Alias(ProgramID program_id, + const Source& source, + const Symbol& sym, + Type* subtype) + : Base(program_id, source), symbol_(sym), subtype_(subtype) { + TINT_ASSERT(subtype_); +} + +Alias::Alias(Alias&&) = default; + +Alias::~Alias() = default; + +std::string Alias::type_name() const { + return "__alias_" + symbol_.to_str() + subtype_->type_name(); +} + +std::string Alias::FriendlyName(const SymbolTable& symbols) const { + return symbols.NameFor(symbol_); +} + +Alias* Alias::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto sym = ctx->Clone(symbol()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, sym, ty); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/alias.h b/src/ast/alias.h new file mode 100644 index 0000000000..d95387d2f8 --- /dev/null +++ b/src/ast/alias.h @@ -0,0 +1,68 @@ +// 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_ALIAS_H_ +#define SRC_AST_ALIAS_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A type alias type. Holds a name and pointer to another type. +class Alias : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param sym the symbol for the alias + /// @param subtype the alias'd type + Alias(ProgramID program_id, + const Source& source, + const Symbol& sym, + Type* subtype); + /// Move constructor + Alias(Alias&&); + /// Destructor + ~Alias() override; + + /// @returns the alias symbol + Symbol symbol() const { return symbol_; } + /// @returns the alias type + Type* type() const { return subtype_; } + + /// @returns the type_name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Alias* Clone(CloneContext* ctx) const override; + + private: + Symbol const symbol_; + Type* const subtype_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_ALIAS_H_ diff --git a/src/ast/alias_test.cc b/src/ast/alias_test.cc new file mode 100644 index 0000000000..ae36314bfd --- /dev/null +++ b/src/ast/alias_test.cc @@ -0,0 +1,170 @@ +// 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/alias.h" +#include "src/ast/access_control.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstAliasTest = TestHelper; + +TEST_F(AstAliasTest, Create) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + EXPECT_EQ(a->symbol(), Symbol(1, ID())); + EXPECT_EQ(a->type(), u32); +} + +TEST_F(AstAliasTest, Is) { + Type* ty = create(Sym("a"), create()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstAliasTest, TypeName) { + auto* at = create(Sym("Particle"), create()); + EXPECT_EQ(at->type_name(), "__alias_$1__i32"); +} + +TEST_F(AstAliasTest, FriendlyName) { + auto* at = create(Sym("Particle"), create()); + EXPECT_EQ(at->FriendlyName(Symbols()), "Particle"); +} + +TEST_F(AstAliasTest, UnwrapIfNeeded_Alias) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + EXPECT_EQ(a->symbol(), Symbol(1, ID())); + EXPECT_EQ(a->type(), u32); + EXPECT_EQ(a->UnwrapIfNeeded(), u32); + EXPECT_EQ(u32->UnwrapIfNeeded(), u32); +} + +TEST_F(AstAliasTest, UnwrapIfNeeded_AccessControl) { + auto* u32 = create(); + auto* ac = create(AccessControl::kReadOnly, u32); + EXPECT_EQ(ac->type(), u32); + EXPECT_EQ(ac->UnwrapIfNeeded(), u32); +} + +TEST_F(AstAliasTest, UnwrapIfNeeded_MultiLevel) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + auto* aa = create(Sym("aa_type"), a); + + EXPECT_EQ(aa->symbol(), Symbol(2, ID())); + EXPECT_EQ(aa->type(), a); + EXPECT_EQ(aa->UnwrapIfNeeded(), u32); +} + +TEST_F(AstAliasTest, UnwrapIfNeeded_MultiLevel_AliasAccessControl) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + + auto* ac = create(AccessControl::kReadWrite, a); + EXPECT_EQ(ac->type(), a); + EXPECT_EQ(ac->UnwrapIfNeeded(), u32); +} + +TEST_F(AstAliasTest, UnwrapAll_TwiceAliasPointerTwiceAlias) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + auto* aa = create(Sym("aa_type"), a); + auto* paa = create(aa, StorageClass::kUniform); + auto* apaa = create(Sym("paa_type"), paa); + auto* aapaa = create(Sym("aapaa_type"), apaa); + + EXPECT_EQ(aapaa->symbol(), Symbol(4, ID())); + EXPECT_EQ(aapaa->type(), apaa); + EXPECT_EQ(aapaa->UnwrapAll(), u32); +} + +TEST_F(AstAliasTest, UnwrapAll_SecondConsecutivePointerBlocksUnrapping) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + auto* aa = create(Sym("aa_type"), a); + + auto* paa = create(aa, StorageClass::kUniform); + auto* ppaa = create(paa, StorageClass::kUniform); + auto* appaa = create(Sym("appaa_type"), ppaa); + EXPECT_EQ(appaa->UnwrapAll(), paa); +} + +TEST_F(AstAliasTest, UnwrapAll_SecondNonConsecutivePointerBlocksUnrapping) { + auto* u32 = create(); + auto* a = create(Sym("a_type"), u32); + auto* aa = create(Sym("aa_type"), a); + auto* paa = create(aa, StorageClass::kUniform); + + auto* apaa = create(Sym("apaa_type"), paa); + auto* aapaa = create(Sym("aapaa_type"), apaa); + auto* paapaa = create(aapaa, StorageClass::kUniform); + auto* apaapaa = create(Sym("apaapaa_type"), paapaa); + + EXPECT_EQ(apaapaa->UnwrapAll(), paa); +} + +TEST_F(AstAliasTest, UnwrapAll_AccessControlPointer) { + auto* u32 = create(); + auto* a = create(AccessControl::kReadOnly, u32); + auto* pa = create(a, StorageClass::kUniform); + EXPECT_EQ(pa->type(), a); + EXPECT_EQ(pa->UnwrapAll(), u32); +} + +TEST_F(AstAliasTest, UnwrapAll_PointerAccessControl) { + auto* u32 = create(); + auto* p = create(u32, StorageClass::kUniform); + auto* a = create(AccessControl::kReadOnly, p); + + EXPECT_EQ(a->type(), p); + EXPECT_EQ(a->UnwrapAll(), u32); +} + +TEST_F(AstAliasTest, UnwrapAliasIfNeeded) { + auto* f32 = create(); + auto* alias1 = create(Sym("alias1"), f32); + auto* alias2 = create(Sym("alias2"), alias1); + auto* alias3 = create(Sym("alias3"), alias2); + EXPECT_EQ(alias3->UnwrapAliasIfNeeded(), f32); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/array.cc b/src/ast/array.cc new file mode 100644 index 0000000000..96ac1de494 --- /dev/null +++ b/src/ast/array.cc @@ -0,0 +1,80 @@ +// 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.h" + +#include + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Array); + +namespace tint { +namespace ast { + +Array::Array(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t size, + ast::DecorationList decorations) + : Base(program_id, source), + subtype_(subtype), + size_(size), + decos_(decorations) {} + +Array::Array(Array&&) = default; + +Array::~Array() = default; + +std::string Array::type_name() const { + TINT_ASSERT(subtype_); + + std::string type_name = "__array" + subtype_->type_name(); + if (!IsRuntimeArray()) { + type_name += "_" + std::to_string(size_); + } + for (auto* deco : decos_) { + if (auto* stride = deco->As()) { + type_name += "_stride_" + std::to_string(stride->stride()); + } + } + + return type_name; +} + +std::string Array::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + for (auto* deco : decos_) { + if (auto* stride = deco->As()) { + out << "[[stride(" << stride->stride() << ")]] "; + } + } + out << "array<" << subtype_->FriendlyName(symbols); + if (!IsRuntimeArray()) { + out << ", " << size_; + } + out << ">"; + return out.str(); +} + +Array* Array::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + auto decos = ctx->Clone(decorations()); + return ctx->dst->create(src, ty, size_, decos); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/array.h b/src/ast/array.h new file mode 100644 index 0000000000..c5ba1b8f09 --- /dev/null +++ b/src/ast/array.h @@ -0,0 +1,79 @@ +// 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_H_ +#define SRC_AST_ARRAY_H_ + +#include + +#include "src/ast/decoration.h" +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// An array type. If size is zero then it is a runtime array. +class Array : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param subtype the type of the array elements + /// @param size the number of elements in the array. `0` represents a + /// runtime-sized array. + /// @param decorations the array decorations + Array(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t size, + ast::DecorationList decorations); + /// Move constructor + Array(Array&&); + ~Array() override; + + /// @returns true if this is a runtime array. + /// i.e. the size is determined at runtime + bool IsRuntimeArray() const { return size_ == 0; } + + /// @returns the array decorations + const ast::DecorationList& decorations() const { return decos_; } + + /// @returns the array type + Type* type() const { return subtype_; } + /// @returns the array size. Size is 0 for a runtime array + uint32_t size() const { return size_; } + + /// @returns the name for the type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Array* Clone(CloneContext* ctx) const override; + + private: + Type* const subtype_; + uint32_t const size_; + ast::DecorationList const decos_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_ARRAY_H_ diff --git a/src/ast/array_test.cc b/src/ast/array_test.cc new file mode 100644 index 0000000000..9619bdf52f --- /dev/null +++ b/src/ast/array_test.cc @@ -0,0 +1,112 @@ +// 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.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstArrayTest = TestHelper; + +TEST_F(AstArrayTest, CreateSizedArray) { + auto* u32 = create(); + auto* arr = create(u32, 3, DecorationList{}); + EXPECT_EQ(arr->type(), u32); + EXPECT_EQ(arr->size(), 3u); + EXPECT_TRUE(arr->Is()); + EXPECT_FALSE(arr->IsRuntimeArray()); +} + +TEST_F(AstArrayTest, CreateRuntimeArray) { + auto* u32 = create(); + auto* arr = create(u32, 0, DecorationList{}); + EXPECT_EQ(arr->type(), u32); + EXPECT_EQ(arr->size(), 0u); + EXPECT_TRUE(arr->Is()); + EXPECT_TRUE(arr->IsRuntimeArray()); +} + +TEST_F(AstArrayTest, Is) { + auto* i32 = create(); + Type* ty = create(i32, 3, DecorationList{}); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstArrayTest, TypeName) { + auto* i32 = create(); + auto* arr = create(i32, 0, DecorationList{}); + EXPECT_EQ(arr->type_name(), "__array__i32"); +} + +TEST_F(AstArrayTest, FriendlyNameRuntimeSized) { + auto* i32 = create(); + auto* arr = create(i32, 0, DecorationList{}); + EXPECT_EQ(arr->FriendlyName(Symbols()), "array"); +} + +TEST_F(AstArrayTest, FriendlyNameStaticSized) { + auto* i32 = create(); + auto* arr = create(i32, 5, DecorationList{}); + EXPECT_EQ(arr->FriendlyName(Symbols()), "array"); +} + +TEST_F(AstArrayTest, FriendlyNameWithStride) { + auto* i32 = create(); + auto* arr = + create(i32, 5, DecorationList{create(32)}); + EXPECT_EQ(arr->FriendlyName(Symbols()), "[[stride(32)]] array"); +} + +TEST_F(AstArrayTest, TypeName_RuntimeArray) { + auto* i32 = create(); + auto* arr = create(i32, 3, DecorationList{}); + EXPECT_EQ(arr->type_name(), "__array__i32_3"); +} + +TEST_F(AstArrayTest, TypeName_WithStride) { + auto* i32 = create(); + auto* arr = + create(i32, 3, DecorationList{create(16)}); + EXPECT_EQ(arr->type_name(), "__array__i32_3_stride_16"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/ast_type.cc b/src/ast/ast_type.cc new file mode 100644 index 0000000000..766b7a5e2b --- /dev/null +++ b/src/ast/ast_type.cc @@ -0,0 +1,142 @@ +// 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.h" + +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Type); + +namespace tint { +namespace ast { + +Type::Type(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +Type::Type(Type&&) = default; + +Type::~Type() = default; + +Type* Type::UnwrapPtrIfNeeded() { + if (auto* ptr = As()) { + return ptr->type(); + } + return this; +} + +Type* Type::UnwrapAliasIfNeeded() { + Type* unwrapped = this; + while (auto* ptr = unwrapped->As()) { + unwrapped = ptr->type(); + } + return unwrapped; +} + +Type* Type::UnwrapIfNeeded() { + auto* where = this; + while (true) { + if (auto* alias = where->As()) { + where = alias->type(); + } else if (auto* access = where->As()) { + where = access->type(); + } else { + break; + } + } + return where; +} + +Type* Type::UnwrapAll() { + return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded(); +} + +bool Type::is_scalar() const { + return IsAnyOf(); +} + +bool Type::is_float_scalar() const { + return Is(); +} + +bool Type::is_float_matrix() const { + return Is( + [](const Matrix* m) { return m->type()->is_float_scalar(); }); +} + +bool Type::is_float_vector() const { + return Is( + [](const Vector* v) { return v->type()->is_float_scalar(); }); +} + +bool Type::is_float_scalar_or_vector() const { + return is_float_scalar() || is_float_vector(); +} + +bool Type::is_float_scalar_or_vector_or_matrix() const { + return is_float_scalar() || is_float_vector() || is_float_matrix(); +} + +bool Type::is_integer_scalar() const { + return IsAnyOf(); +} + +bool Type::is_unsigned_integer_vector() const { + return Is([](const Vector* v) { return v->type()->Is(); }); +} + +bool Type::is_signed_integer_vector() const { + return Is([](const Vector* v) { return v->type()->Is(); }); +} + +bool Type::is_unsigned_scalar_or_vector() const { + return Is() || is_unsigned_integer_vector(); +} + +bool Type::is_signed_scalar_or_vector() const { + return Is() || is_signed_integer_vector(); +} + +bool Type::is_integer_scalar_or_vector() const { + return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector(); +} + +bool Type::is_bool_vector() const { + return Is([](const Vector* v) { return v->type()->Is(); }); +} + +bool Type::is_bool_scalar_or_vector() const { + return Is() || is_bool_vector(); +} + +bool Type::is_handle() const { + return IsAnyOf(); +} + +void Type::to_str(const sem::Info&, std::ostream& out, size_t indent) const { + make_indent(out, indent); + out << type_name(); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/bool.cc b/src/ast/bool.cc new file mode 100644 index 0000000000..d212812999 --- /dev/null +++ b/src/ast/bool.cc @@ -0,0 +1,45 @@ +// 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/bool.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Bool); + +namespace tint { +namespace ast { + +Bool::Bool(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +Bool::Bool(Bool&&) = default; + +Bool::~Bool() = default; + +std::string Bool::type_name() const { + return "__bool"; +} + +std::string Bool::FriendlyName(const SymbolTable&) const { + return "bool"; +} + +Bool* Bool::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/bool.h b/src/ast/bool.h new file mode 100644 index 0000000000..ad5b858345 --- /dev/null +++ b/src/ast/bool.h @@ -0,0 +1,59 @@ +// 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_BOOL_H_ +#define SRC_AST_BOOL_H_ + +#include + +#include "src/ast/type.h" + +// X11 likes to #define Bool leading to confusing error messages. +// If its defined, undefine it. +#ifdef Bool +#undef Bool +#endif + +namespace tint { +namespace ast { + +/// A boolean type +class Bool : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + Bool(ProgramID program_id, const Source& source); + /// Move constructor + Bool(Bool&&); + ~Bool() override; + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Bool* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_BOOL_H_ diff --git a/src/ast/bool_test.cc b/src/ast/bool_test.cc new file mode 100644 index 0000000000..3d2b2a8117 --- /dev/null +++ b/src/ast/bool_test.cc @@ -0,0 +1,65 @@ +// 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/bool.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstBoolTest = TestHelper; + +TEST_F(AstBoolTest, Is) { + Type* ty = create(); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstBoolTest, TypeName) { + auto* b = create(); + EXPECT_EQ(b->type_name(), "__bool"); +} + +TEST_F(AstBoolTest, FriendlyName) { + auto* b = create(); + EXPECT_EQ(b->FriendlyName(Symbols()), "bool"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/depth_texture.cc b/src/ast/depth_texture.cc new file mode 100644 index 0000000000..b669113f63 --- /dev/null +++ b/src/ast/depth_texture.cc @@ -0,0 +1,61 @@ +// 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/depth_texture.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::DepthTexture); + +namespace tint { +namespace ast { +namespace { + +bool IsValidDepthDimension(TextureDimension dim) { + return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray || + dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray; +} + +} // namespace + +DepthTexture::DepthTexture(ProgramID program_id, + const Source& source, + TextureDimension dim) + : Base(program_id, source, dim) { + TINT_ASSERT(IsValidDepthDimension(dim)); +} + +DepthTexture::DepthTexture(DepthTexture&&) = default; + +DepthTexture::~DepthTexture() = default; + +std::string DepthTexture::type_name() const { + std::ostringstream out; + out << "__depth_texture_" << dim(); + return out.str(); +} + +std::string DepthTexture::FriendlyName(const SymbolTable&) const { + std::ostringstream out; + out << "texture_depth_" << dim(); + return out.str(); +} + +DepthTexture* DepthTexture::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src, dim()); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/depth_texture.h b/src/ast/depth_texture.h new file mode 100644 index 0000000000..7fe82e514d --- /dev/null +++ b/src/ast/depth_texture.h @@ -0,0 +1,56 @@ +// 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_DEPTH_TEXTURE_H_ +#define SRC_AST_DEPTH_TEXTURE_H_ + +#include + +#include "src/ast/texture.h" + +namespace tint { +namespace ast { + +/// A depth texture type. +class DepthTexture : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param dim the dimensionality of the texture + DepthTexture(ProgramID program_id, + const Source& source, + TextureDimension dim); + /// Move constructor + DepthTexture(DepthTexture&&); + ~DepthTexture() override; + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + DepthTexture* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_DEPTH_TEXTURE_H_ diff --git a/src/ast/depth_texture_test.cc b/src/ast/depth_texture_test.cc new file mode 100644 index 0000000000..a682d9bbf5 --- /dev/null +++ b/src/ast/depth_texture_test.cc @@ -0,0 +1,80 @@ +// 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/depth_texture.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampled_texture.h" +#include "src/ast/sampler.h" +#include "src/ast/storage_texture.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstDepthTextureTest = TestHelper; + +TEST_F(AstDepthTextureTest, Is) { + Type* ty = create(TextureDimension::kCube); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstDepthTextureTest, IsTexture) { + Texture* ty = create(TextureDimension::kCube); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstDepthTextureTest, Dim) { + auto* d = create(TextureDimension::kCube); + EXPECT_EQ(d->dim(), TextureDimension::kCube); +} + +TEST_F(AstDepthTextureTest, TypeName) { + auto* d = create(TextureDimension::kCube); + EXPECT_EQ(d->type_name(), "__depth_texture_cube"); +} + +TEST_F(AstDepthTextureTest, FriendlyName) { + auto* d = create(TextureDimension::kCube); + EXPECT_EQ(d->FriendlyName(Symbols()), "texture_depth_cube"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/f32.cc b/src/ast/f32.cc new file mode 100644 index 0000000000..66a8fe0f12 --- /dev/null +++ b/src/ast/f32.cc @@ -0,0 +1,45 @@ +// 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/f32.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::F32); + +namespace tint { +namespace ast { + +F32::F32(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +F32::F32(F32&&) = default; + +F32::~F32() = default; + +std::string F32::type_name() const { + return "__f32"; +} + +std::string F32::FriendlyName(const SymbolTable&) const { + return "f32"; +} + +F32* F32::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/f32.h b/src/ast/f32.h new file mode 100644 index 0000000000..42e9bc7851 --- /dev/null +++ b/src/ast/f32.h @@ -0,0 +1,53 @@ +// 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_F32_H_ +#define SRC_AST_F32_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A float 32 type +class F32 : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + F32(ProgramID program_id, const Source& source); + /// Move constructor + F32(F32&&); + ~F32() override; + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + F32* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_F32_H_ diff --git a/src/ast/f32_test.cc b/src/ast/f32_test.cc new file mode 100644 index 0000000000..2045d832da --- /dev/null +++ b/src/ast/f32_test.cc @@ -0,0 +1,65 @@ +// 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/f32.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstF32Test = TestHelper; + +TEST_F(AstF32Test, Is) { + Type* ty = create(); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstF32Test, TypeName) { + auto* f = create(); + EXPECT_EQ(f->type_name(), "__f32"); +} + +TEST_F(AstF32Test, FriendlyName) { + auto* f = create(); + EXPECT_EQ(f->FriendlyName(Symbols()), "f32"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/i32.cc b/src/ast/i32.cc new file mode 100644 index 0000000000..358e775875 --- /dev/null +++ b/src/ast/i32.cc @@ -0,0 +1,45 @@ +// 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/i32.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::I32); + +namespace tint { +namespace ast { + +I32::I32(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +I32::I32(I32&&) = default; + +I32::~I32() = default; + +std::string I32::type_name() const { + return "__i32"; +} + +std::string I32::FriendlyName(const SymbolTable&) const { + return "i32"; +} + +I32* I32::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/i32.h b/src/ast/i32.h new file mode 100644 index 0000000000..182f102925 --- /dev/null +++ b/src/ast/i32.h @@ -0,0 +1,53 @@ +// 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_I32_H_ +#define SRC_AST_I32_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A signed int 32 type. +class I32 : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + I32(ProgramID program_id, const Source& source); + /// Move constructor + I32(I32&&); + ~I32() override; + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + I32* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_I32_H_ diff --git a/src/ast/i32_test.cc b/src/ast/i32_test.cc new file mode 100644 index 0000000000..7a8570796f --- /dev/null +++ b/src/ast/i32_test.cc @@ -0,0 +1,66 @@ +// 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/i32.h" + +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstI32Test = TestHelper; + +TEST_F(AstI32Test, Is) { + Type* ty = create(); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstI32Test, TypeName) { + auto* i = create(); + EXPECT_EQ(i->type_name(), "__i32"); +} + +TEST_F(AstI32Test, FriendlyName) { + auto* i = create(); + EXPECT_EQ(i->FriendlyName(Symbols()), "i32"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/intrinsic_texture_helper_test.cc b/src/ast/intrinsic_texture_helper_test.cc index e044cd6354..1669270df8 100644 --- a/src/ast/intrinsic_texture_helper_test.cc +++ b/src/ast/intrinsic_texture_helper_test.cc @@ -63,7 +63,7 @@ TextureOverloadCase::TextureOverloadCase( TextureOverloadCase::TextureOverloadCase( ValidTextureOverload o, const char* d, - AccessControl access, + AccessControl::Access access, sem::ImageFormat i, sem::TextureDimension dims, TextureDataType datatype, diff --git a/src/ast/intrinsic_texture_helper_test.h b/src/ast/intrinsic_texture_helper_test.h index e5c5628e6f..b7a9a80e02 100644 --- a/src/ast/intrinsic_texture_helper_test.h +++ b/src/ast/intrinsic_texture_helper_test.h @@ -198,7 +198,7 @@ struct TextureOverloadCase { /// Constructor for textureLoad() with storage textures TextureOverloadCase(ValidTextureOverload, const char*, - AccessControl, + AccessControl::Access, sem::ImageFormat, sem::TextureDimension, TextureDataType, @@ -236,7 +236,7 @@ struct TextureOverloadCase { sem::SamplerKind const sampler_kind = sem::SamplerKind::kSampler; /// The access control for the storage texture /// Used only when texture_kind is kStorage - AccessControl const access_control = AccessControl::kReadWrite; + AccessControl::Access const access_control = AccessControl::kReadWrite; /// The image format for the storage texture /// Used only when texture_kind is kStorage sem::ImageFormat const image_format = sem::ImageFormat::kNone; diff --git a/src/ast/matrix.cc b/src/ast/matrix.cc new file mode 100644 index 0000000000..da8e019a0d --- /dev/null +++ b/src/ast/matrix.cc @@ -0,0 +1,63 @@ +// 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/matrix.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Matrix); + +namespace tint { +namespace ast { + +Matrix::Matrix(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t rows, + uint32_t columns) + : Base(program_id, source), + subtype_(subtype), + rows_(rows), + columns_(columns) { + TINT_ASSERT(rows > 1); + TINT_ASSERT(rows < 5); + TINT_ASSERT(columns > 1); + TINT_ASSERT(columns < 5); +} + +Matrix::Matrix(Matrix&&) = default; + +Matrix::~Matrix() = default; + +std::string Matrix::type_name() const { + return "__mat_" + std::to_string(rows_) + "_" + std::to_string(columns_) + + subtype_->type_name(); +} + +std::string Matrix::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + out << "mat" << columns_ << "x" << rows_ << "<" + << subtype_->FriendlyName(symbols) << ">"; + return out.str(); +} + +Matrix* Matrix::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, ty, rows_, columns_); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/matrix.h b/src/ast/matrix.h new file mode 100644 index 0000000000..1a419dd0e7 --- /dev/null +++ b/src/ast/matrix.h @@ -0,0 +1,72 @@ +// 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_MATRIX_H_ +#define SRC_AST_MATRIX_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A matrix type +class Matrix : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param subtype type matrix type + /// @param rows the number of rows in the matrix + /// @param columns the number of columns in the matrix + Matrix(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t rows, + uint32_t columns); + /// Move constructor + Matrix(Matrix&&); + ~Matrix() override; + + /// @returns the type of the matrix + Type* type() const { return subtype_; } + /// @returns the number of rows in the matrix + uint32_t rows() const { return rows_; } + /// @returns the number of columns in the matrix + uint32_t columns() const { return columns_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Matrix* Clone(CloneContext* ctx) const override; + + private: + Type* const subtype_; + uint32_t const rows_; + uint32_t const columns_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_MATRIX_H_ diff --git a/src/ast/matrix_test.cc b/src/ast/matrix_test.cc new file mode 100644 index 0000000000..fc5e40b5c7 --- /dev/null +++ b/src/ast/matrix_test.cc @@ -0,0 +1,76 @@ +// 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/matrix.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstMatrixTest = TestHelper; + +TEST_F(AstMatrixTest, Creation) { + auto* i32 = create(); + auto* m = create(i32, 2, 4); + EXPECT_EQ(m->type(), i32); + EXPECT_EQ(m->rows(), 2u); + EXPECT_EQ(m->columns(), 4u); +} + +TEST_F(AstMatrixTest, Is) { + auto* i32 = create(); + Type* ty = create(i32, 2, 3); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstMatrixTest, TypeName) { + auto* i32 = create(); + auto* m = create(i32, 2, 3); + EXPECT_EQ(m->type_name(), "__mat_2_3__i32"); +} + +TEST_F(AstMatrixTest, FriendlyName) { + auto* i32 = create(); + auto* m = create(i32, 3, 2); + EXPECT_EQ(m->FriendlyName(Symbols()), "mat2x3"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/module.cc b/src/ast/module.cc index 31ac2f38c9..d6cc39a08c 100644 --- a/src/ast/module.cc +++ b/src/ast/module.cc @@ -89,7 +89,6 @@ void Module::to_str(const sem::Info& sem, str->impl()->to_str(sem, out, indent); } } else if (auto* str = ty->As()) { - out << str->symbol().to_str() << " "; str->impl()->to_str(sem, out, indent); } } diff --git a/src/ast/multisampled_texture.cc b/src/ast/multisampled_texture.cc new file mode 100644 index 0000000000..5f907ab8eb --- /dev/null +++ b/src/ast/multisampled_texture.cc @@ -0,0 +1,58 @@ +// 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/multisampled_texture.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::MultisampledTexture); + +namespace tint { +namespace ast { + +MultisampledTexture::MultisampledTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + Type* type) + : Base(program_id, source, dim), type_(type) { + TINT_ASSERT(type_); +} + +MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default; + +MultisampledTexture::~MultisampledTexture() = default; + +std::string MultisampledTexture::type_name() const { + std::ostringstream out; + out << "__multisampled_texture_" << dim() << type_->type_name(); + return out.str(); +} + +std::string MultisampledTexture::FriendlyName( + const SymbolTable& symbols) const { + std::ostringstream out; + out << "texture_multisampled_" << dim() << "<" << type_->FriendlyName(symbols) + << ">"; + return out.str(); +} + +MultisampledTexture* MultisampledTexture::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, dim(), ty); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/multisampled_texture.h b/src/ast/multisampled_texture.h new file mode 100644 index 0000000000..9fcc2a8b8e --- /dev/null +++ b/src/ast/multisampled_texture.h @@ -0,0 +1,64 @@ +// 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_MULTISAMPLED_TEXTURE_H_ +#define SRC_AST_MULTISAMPLED_TEXTURE_H_ + +#include + +#include "src/ast/texture.h" + +namespace tint { +namespace ast { + +/// A multisampled texture type. +class MultisampledTexture : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param dim the dimensionality of the texture + /// @param type the data type of the multisampled texture + MultisampledTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + Type* type); + /// Move constructor + MultisampledTexture(MultisampledTexture&&); + ~MultisampledTexture() override; + + /// @returns the subtype of the sampled texture + Type* type() const { return type_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + MultisampledTexture* Clone(CloneContext* ctx) const override; + + private: + Type* const type_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_MULTISAMPLED_TEXTURE_H_ diff --git a/src/ast/multisampled_texture_test.cc b/src/ast/multisampled_texture_test.cc new file mode 100644 index 0000000000..277c25a283 --- /dev/null +++ b/src/ast/multisampled_texture_test.cc @@ -0,0 +1,94 @@ +// 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/multisampled_texture.h" + +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/depth_texture.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampled_texture.h" +#include "src/ast/sampler.h" +#include "src/ast/storage_texture.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstMultisampledTextureTest = TestHelper; + +TEST_F(AstMultisampledTextureTest, Is) { + auto* f32 = create(); + Type* ty = create(TextureDimension::kCube, f32); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstMultisampledTextureTest, IsTexture) { + auto* f32 = create(); + Texture* ty = create(TextureDimension::kCube, f32); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstMultisampledTextureTest, Dim) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->dim(), TextureDimension::k3d); +} + +TEST_F(AstMultisampledTextureTest, Type) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->type(), f32); +} + +TEST_F(AstMultisampledTextureTest, TypeName) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->type_name(), "__multisampled_texture_3d__f32"); +} + +TEST_F(AstMultisampledTextureTest, FriendlyName) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->FriendlyName(Symbols()), "texture_multisampled_3d"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/pointer.cc b/src/ast/pointer.cc new file mode 100644 index 0000000000..3a968dc2c8 --- /dev/null +++ b/src/ast/pointer.cc @@ -0,0 +1,60 @@ +// 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/pointer.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Pointer); + +namespace tint { +namespace ast { + +Pointer::Pointer(ProgramID program_id, + const Source& source, + Type* subtype, + ast::StorageClass storage_class) + : Base(program_id, source), + subtype_(subtype), + storage_class_(storage_class) {} + +std::string Pointer::type_name() const { + std::ostringstream out; + out << "__ptr_" << storage_class_ << subtype_->type_name(); + return out.str(); +} + +std::string Pointer::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + out << "ptr<"; + if (storage_class_ != ast::StorageClass::kNone) { + out << storage_class_ << ", "; + } + out << subtype_->FriendlyName(symbols) << ">"; + return out.str(); +} + +Pointer::Pointer(Pointer&&) = default; + +Pointer::~Pointer() = default; + +Pointer* Pointer::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, ty, storage_class_); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/pointer.h b/src/ast/pointer.h new file mode 100644 index 0000000000..55882edabc --- /dev/null +++ b/src/ast/pointer.h @@ -0,0 +1,68 @@ +// 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_POINTER_H_ +#define SRC_AST_POINTER_H_ + +#include + +#include "src/ast/storage_class.h" +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A pointer type. +class Pointer : public Castable { + public: + /// Construtor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param subtype the pointee type + /// @param storage_class the storage class of the pointer + Pointer(ProgramID program_id, + const Source& source, + Type* subtype, + ast::StorageClass storage_class); + /// Move constructor + Pointer(Pointer&&); + ~Pointer() override; + + /// @returns the pointee type + Type* type() const { return subtype_; } + /// @returns the storage class of the pointer + ast::StorageClass storage_class() const { return storage_class_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Pointer* Clone(CloneContext* ctx) const override; + + private: + Type* const subtype_; + ast::StorageClass const storage_class_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_POINTER_H_ diff --git a/src/ast/pointer_test.cc b/src/ast/pointer_test.cc new file mode 100644 index 0000000000..9e11d2e6ff --- /dev/null +++ b/src/ast/pointer_test.cc @@ -0,0 +1,81 @@ +// 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/pointer.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstPointerTest = TestHelper; + +TEST_F(AstPointerTest, Creation) { + auto* i32 = create(); + auto* p = create(i32, ast::StorageClass::kStorage); + EXPECT_EQ(p->type(), i32); + EXPECT_EQ(p->storage_class(), ast::StorageClass::kStorage); +} + +TEST_F(AstPointerTest, Is) { + auto* i32 = create(); + Type* ty = create(i32, ast::StorageClass::kFunction); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstPointerTest, TypeName) { + auto* i32 = create(); + auto* p = create(i32, ast::StorageClass::kWorkgroup); + EXPECT_EQ(p->type_name(), "__ptr_workgroup__i32"); +} + +TEST_F(AstPointerTest, FriendlyNameWithStorageClass) { + auto* i32 = create(); + auto* p = create(i32, ast::StorageClass::kWorkgroup); + EXPECT_EQ(p->FriendlyName(Symbols()), "ptr"); +} + +TEST_F(AstPointerTest, FriendlyNameWithoutStorageClass) { + auto* i32 = create(); + auto* p = create(i32, ast::StorageClass::kNone); + EXPECT_EQ(p->FriendlyName(Symbols()), "ptr"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/sampled_texture.cc b/src/ast/sampled_texture.cc new file mode 100644 index 0000000000..9e1ad0d287 --- /dev/null +++ b/src/ast/sampled_texture.cc @@ -0,0 +1,56 @@ +// 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/sampled_texture.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::SampledTexture); + +namespace tint { +namespace ast { + +SampledTexture::SampledTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + Type* type) + : Base(program_id, source, dim), type_(type) { + TINT_ASSERT(type_); +} + +SampledTexture::SampledTexture(SampledTexture&&) = default; + +SampledTexture::~SampledTexture() = default; + +std::string SampledTexture::type_name() const { + std::ostringstream out; + out << "__sampled_texture_" << dim() << type_->type_name(); + return out.str(); +} + +std::string SampledTexture::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + out << "texture_" << dim() << "<" << type_->FriendlyName(symbols) << ">"; + return out.str(); +} + +SampledTexture* SampledTexture::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, dim(), ty); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/sampled_texture.h b/src/ast/sampled_texture.h new file mode 100644 index 0000000000..f7d9af9315 --- /dev/null +++ b/src/ast/sampled_texture.h @@ -0,0 +1,64 @@ +// 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_SAMPLED_TEXTURE_H_ +#define SRC_AST_SAMPLED_TEXTURE_H_ + +#include + +#include "src/ast/texture.h" + +namespace tint { +namespace ast { + +/// A sampled texture type. +class SampledTexture : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param dim the dimensionality of the texture + /// @param type the data type of the sampled texture + SampledTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + Type* type); + /// Move constructor + SampledTexture(SampledTexture&&); + ~SampledTexture() override; + + /// @returns the subtype of the sampled texture + Type* type() const { return type_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + SampledTexture* Clone(CloneContext* ctx) const override; + + private: + Type* const type_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_SAMPLED_TEXTURE_H_ diff --git a/src/ast/sampled_texture_test.cc b/src/ast/sampled_texture_test.cc new file mode 100644 index 0000000000..4cba040bfa --- /dev/null +++ b/src/ast/sampled_texture_test.cc @@ -0,0 +1,92 @@ +// 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/sampled_texture.h" + +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/depth_texture.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/storage_texture.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstSampledTextureTest = TestHelper; + +TEST_F(AstSampledTextureTest, Is) { + auto* f32 = create(); + Type* ty = create(TextureDimension::kCube, f32); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstSampledTextureTest, IsTexture) { + auto* f32 = create(); + Texture* ty = create(TextureDimension::kCube, f32); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstSampledTextureTest, Dim) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->dim(), TextureDimension::k3d); +} + +TEST_F(AstSampledTextureTest, Type) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->type(), f32); +} + +TEST_F(AstSampledTextureTest, TypeName) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->type_name(), "__sampled_texture_3d__f32"); +} + +TEST_F(AstSampledTextureTest, FriendlyName) { + auto* f32 = create(); + auto* s = create(TextureDimension::k3d, f32); + EXPECT_EQ(s->FriendlyName(Symbols()), "texture_3d"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/sampler.cc b/src/ast/sampler.cc new file mode 100644 index 0000000000..bcf95c885e --- /dev/null +++ b/src/ast/sampler.cc @@ -0,0 +1,58 @@ +// 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/sampler.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Sampler); + +namespace tint { +namespace ast { + +std::ostream& operator<<(std::ostream& out, SamplerKind kind) { + switch (kind) { + case SamplerKind::kSampler: + out << "sampler"; + break; + case SamplerKind::kComparisonSampler: + out << "comparison_sampler"; + break; + } + return out; +} + +Sampler::Sampler(ProgramID program_id, const Source& source, SamplerKind kind) + : Base(program_id, source), kind_(kind) {} + +Sampler::Sampler(Sampler&&) = default; + +Sampler::~Sampler() = default; + +std::string Sampler::type_name() const { + return std::string("__sampler_") + + (kind_ == SamplerKind::kSampler ? "sampler" : "comparison"); +} + +std::string Sampler::FriendlyName(const SymbolTable&) const { + return kind_ == SamplerKind::kSampler ? "sampler" : "sampler_comparison"; +} + +Sampler* Sampler::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src, kind_); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/sampler.h b/src/ast/sampler.h new file mode 100644 index 0000000000..3800de90b8 --- /dev/null +++ b/src/ast/sampler.h @@ -0,0 +1,76 @@ +// 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_SAMPLER_H_ +#define SRC_AST_SAMPLER_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// The different kinds of samplers +enum class SamplerKind { + /// A regular sampler + kSampler, + /// A comparison sampler + kComparisonSampler +}; + +/// @param out the std::ostream to write to +/// @param kind the SamplerKind +/// @return the std::ostream so calls can be chained +std::ostream& operator<<(std::ostream& out, SamplerKind kind); + +/// A sampler type. +class Sampler : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param kind the kind of sampler + Sampler(ProgramID program_id, const Source& source, SamplerKind kind); + /// Move constructor + Sampler(Sampler&&); + ~Sampler() override; + + /// @returns the sampler type + SamplerKind kind() const { return kind_; } + + /// @returns true if this is a comparison sampler + bool IsComparison() const { return kind_ == SamplerKind::kComparisonSampler; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Sampler* Clone(CloneContext* ctx) const override; + + private: + SamplerKind const kind_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_SAMPLER_H_ diff --git a/src/ast/sampler_test.cc b/src/ast/sampler_test.cc new file mode 100644 index 0000000000..9ddf1fe43d --- /dev/null +++ b/src/ast/sampler_test.cc @@ -0,0 +1,86 @@ +// 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/sampler.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstSamplerTest = TestHelper; + +TEST_F(AstSamplerTest, Creation) { + auto* s = create(SamplerKind::kSampler); + EXPECT_EQ(s->kind(), SamplerKind::kSampler); +} + +TEST_F(AstSamplerTest, Creation_ComparisonSampler) { + auto* s = create(SamplerKind::kComparisonSampler); + EXPECT_EQ(s->kind(), SamplerKind::kComparisonSampler); + EXPECT_TRUE(s->IsComparison()); +} + +TEST_F(AstSamplerTest, Is) { + Type* ty = create(SamplerKind::kSampler); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstSamplerTest, TypeName_Sampler) { + auto* s = create(SamplerKind::kSampler); + EXPECT_EQ(s->type_name(), "__sampler_sampler"); +} + +TEST_F(AstSamplerTest, TypeName_Comparison) { + auto* s = create(SamplerKind::kComparisonSampler); + EXPECT_EQ(s->type_name(), "__sampler_comparison"); +} + +TEST_F(AstSamplerTest, FriendlyNameSampler) { + auto* s = create(SamplerKind::kSampler); + EXPECT_EQ(s->FriendlyName(Symbols()), "sampler"); +} + +TEST_F(AstSamplerTest, FriendlyNameComparisonSampler) { + auto* s = create(SamplerKind::kComparisonSampler); + EXPECT_EQ(s->FriendlyName(Symbols()), "sampler_comparison"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/storage_texture.cc b/src/ast/storage_texture.cc new file mode 100644 index 0000000000..f1f23d61d4 --- /dev/null +++ b/src/ast/storage_texture.cc @@ -0,0 +1,227 @@ +// 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/storage_texture.h" + +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/u32.h" +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::StorageTexture); + +namespace tint { +namespace ast { + +// Note, these names match the names in the WGSL spec. This behaviour is used +// in the WGSL writer to emit the texture format names. +std::ostream& operator<<(std::ostream& out, ImageFormat format) { + switch (format) { + case ImageFormat::kNone: + out << "none"; + break; + case ImageFormat::kR8Unorm: + out << "r8unorm"; + break; + case ImageFormat::kR8Snorm: + out << "r8snorm"; + break; + case ImageFormat::kR8Uint: + out << "r8uint"; + break; + case ImageFormat::kR8Sint: + out << "r8sint"; + break; + case ImageFormat::kR16Uint: + out << "r16uint"; + break; + case ImageFormat::kR16Sint: + out << "r16sint"; + break; + case ImageFormat::kR16Float: + out << "r16float"; + break; + case ImageFormat::kRg8Unorm: + out << "rg8unorm"; + break; + case ImageFormat::kRg8Snorm: + out << "rg8snorm"; + break; + case ImageFormat::kRg8Uint: + out << "rg8uint"; + break; + case ImageFormat::kRg8Sint: + out << "rg8sint"; + break; + case ImageFormat::kR32Uint: + out << "r32uint"; + break; + case ImageFormat::kR32Sint: + out << "r32sint"; + break; + case ImageFormat::kR32Float: + out << "r32float"; + break; + case ImageFormat::kRg16Uint: + out << "rg16uint"; + break; + case ImageFormat::kRg16Sint: + out << "rg16sint"; + break; + case ImageFormat::kRg16Float: + out << "rg16float"; + break; + case ImageFormat::kRgba8Unorm: + out << "rgba8unorm"; + break; + case ImageFormat::kRgba8UnormSrgb: + out << "rgba8unorm_srgb"; + break; + case ImageFormat::kRgba8Snorm: + out << "rgba8snorm"; + break; + case ImageFormat::kRgba8Uint: + out << "rgba8uint"; + break; + case ImageFormat::kRgba8Sint: + out << "rgba8sint"; + break; + case ImageFormat::kBgra8Unorm: + out << "bgra8unorm"; + break; + case ImageFormat::kBgra8UnormSrgb: + out << "bgra8unorm_srgb"; + break; + case ImageFormat::kRgb10A2Unorm: + out << "rgb10a2unorm"; + break; + case ImageFormat::kRg11B10Float: + out << "rg11b10float"; + break; + case ImageFormat::kRg32Uint: + out << "rg32uint"; + break; + case ImageFormat::kRg32Sint: + out << "rg32sint"; + break; + case ImageFormat::kRg32Float: + out << "rg32float"; + break; + case ImageFormat::kRgba16Uint: + out << "rgba16uint"; + break; + case ImageFormat::kRgba16Sint: + out << "rgba16sint"; + break; + case ImageFormat::kRgba16Float: + out << "rgba16float"; + break; + case ImageFormat::kRgba32Uint: + out << "rgba32uint"; + break; + case ImageFormat::kRgba32Sint: + out << "rgba32sint"; + break; + case ImageFormat::kRgba32Float: + out << "rgba32float"; + break; + } + return out; +} + +StorageTexture::StorageTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + ImageFormat format, + Type* subtype) + : Base(program_id, source, dim), image_format_(format), subtype_(subtype) {} + +StorageTexture::StorageTexture(StorageTexture&&) = default; + +StorageTexture::~StorageTexture() = default; + +std::string StorageTexture::type_name() const { + std::ostringstream out; + out << "__storage_texture_" << dim() << "_" << image_format_; + return out.str(); +} + +std::string StorageTexture::FriendlyName(const SymbolTable&) const { + std::ostringstream out; + out << "texture_storage_" << dim() << "<" << image_format_ << ">"; + return out.str(); +} + +StorageTexture* StorageTexture::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, dim(), image_format_, ty); +} + +Type* StorageTexture::SubtypeFor(ImageFormat format, ProgramBuilder& builder) { + switch (format) { + case ImageFormat::kR8Uint: + case ImageFormat::kR16Uint: + case ImageFormat::kRg8Uint: + case ImageFormat::kR32Uint: + case ImageFormat::kRg16Uint: + case ImageFormat::kRgba8Uint: + case ImageFormat::kRg32Uint: + case ImageFormat::kRgba16Uint: + case ImageFormat::kRgba32Uint: { + return builder.create(); + } + + case ImageFormat::kR8Sint: + case ImageFormat::kR16Sint: + case ImageFormat::kRg8Sint: + case ImageFormat::kR32Sint: + case ImageFormat::kRg16Sint: + case ImageFormat::kRgba8Sint: + case ImageFormat::kRg32Sint: + case ImageFormat::kRgba16Sint: + case ImageFormat::kRgba32Sint: { + return builder.create(); + } + + case ImageFormat::kR8Unorm: + case ImageFormat::kRg8Unorm: + case ImageFormat::kRgba8Unorm: + case ImageFormat::kRgba8UnormSrgb: + case ImageFormat::kBgra8Unorm: + case ImageFormat::kBgra8UnormSrgb: + case ImageFormat::kRgb10A2Unorm: + case ImageFormat::kR8Snorm: + case ImageFormat::kRg8Snorm: + case ImageFormat::kRgba8Snorm: + case ImageFormat::kR16Float: + case ImageFormat::kR32Float: + case ImageFormat::kRg16Float: + case ImageFormat::kRg11B10Float: + case ImageFormat::kRg32Float: + case ImageFormat::kRgba16Float: + case ImageFormat::kRgba32Float: { + return builder.create(); + } + + case ImageFormat::kNone: + break; + } + + return nullptr; +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/storage_texture.h b/src/ast/storage_texture.h new file mode 100644 index 0000000000..bdf16b3902 --- /dev/null +++ b/src/ast/storage_texture.h @@ -0,0 +1,123 @@ +// 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_STORAGE_TEXTURE_H_ +#define SRC_AST_STORAGE_TEXTURE_H_ + +#include + +#include "src/ast/texture.h" + +namespace tint { +namespace ast { + +class Manager; + +/// The image format in the storage texture +enum class ImageFormat { + kNone = -1, + kR8Unorm, + kR8Snorm, + kR8Uint, + kR8Sint, + kR16Uint, + kR16Sint, + kR16Float, + kRg8Unorm, + kRg8Snorm, + kRg8Uint, + kRg8Sint, + kR32Uint, + kR32Sint, + kR32Float, + kRg16Uint, + kRg16Sint, + kRg16Float, + kRgba8Unorm, + kRgba8UnormSrgb, + kRgba8Snorm, + kRgba8Uint, + kRgba8Sint, + kBgra8Unorm, + kBgra8UnormSrgb, + kRgb10A2Unorm, + kRg11B10Float, + kRg32Uint, + kRg32Sint, + kRg32Float, + kRgba16Uint, + kRgba16Sint, + kRgba16Float, + kRgba32Uint, + kRgba32Sint, + kRgba32Float, +}; + +/// @param out the std::ostream to write to +/// @param format the ImageFormat +/// @return the std::ostream so calls can be chained +std::ostream& operator<<(std::ostream& out, ImageFormat format); + +/// A storage texture type. +class StorageTexture : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param dim the dimensionality of the texture + /// @param format the image format of the texture + /// @param subtype the storage subtype. Use SubtypeFor() to calculate this. + StorageTexture(ProgramID program_id, + const Source& source, + TextureDimension dim, + ImageFormat format, + Type* subtype); + + /// Move constructor + StorageTexture(StorageTexture&&); + ~StorageTexture() override; + + /// @returns the storage subtype + Type* type() const { return subtype_; } + + /// @returns the image format + ImageFormat image_format() const { return image_format_; } + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + StorageTexture* Clone(CloneContext* ctx) const override; + + /// @param format the storage texture image format + /// @param builder the ProgramBuilder used to build the returned type + /// @returns the storage texture subtype for the given ImageFormat + static Type* SubtypeFor(ImageFormat format, ProgramBuilder& builder); + + private: + ImageFormat const image_format_; + Type* const subtype_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_STORAGE_TEXTURE_H_ diff --git a/src/ast/storage_texture_test.cc b/src/ast/storage_texture_test.cc new file mode 100644 index 0000000000..0f29196bc1 --- /dev/null +++ b/src/ast/storage_texture_test.cc @@ -0,0 +1,128 @@ +// 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/storage_texture.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/depth_texture.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampled_texture.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstStorageTextureTest = TestHelper; + +TEST_F(AstStorageTextureTest, Is) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + Type* ty = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstStorageTextureTest, IsTexture) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + Texture* ty = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); +} + +TEST_F(AstStorageTextureTest, Dim) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + auto* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_EQ(s->dim(), TextureDimension::k2dArray); +} + +TEST_F(AstStorageTextureTest, Format) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + auto* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_EQ(s->image_format(), ImageFormat::kRgba32Float); +} + +TEST_F(AstStorageTextureTest, TypeName) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + auto* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_EQ(s->type_name(), "__storage_texture_2d_array_rgba32float"); +} + +TEST_F(AstStorageTextureTest, FriendlyName) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + auto* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + EXPECT_EQ(s->FriendlyName(Symbols()), + "texture_storage_2d_array"); +} + +TEST_F(AstStorageTextureTest, F32) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this); + Type* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Float, subtype); + + ASSERT_TRUE(s->Is()); + ASSERT_TRUE(s->Is()); + EXPECT_TRUE(s->As()->type()->Is()); +} + +TEST_F(AstStorageTextureTest, U32) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRg32Uint, *this); + Type* s = create(TextureDimension::k2dArray, + ImageFormat::kRg32Uint, subtype); + + ASSERT_TRUE(s->Is()); + ASSERT_TRUE(s->Is()); + EXPECT_TRUE(s->As()->type()->Is()); +} + +TEST_F(AstStorageTextureTest, I32) { + auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Sint, *this); + Type* s = create(TextureDimension::k2dArray, + ImageFormat::kRgba32Sint, subtype); + + ASSERT_TRUE(s->Is()); + ASSERT_TRUE(s->Is()); + EXPECT_TRUE(s->As()->type()->Is()); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/struct.cc b/src/ast/struct.cc index a3a396dcbe..1ebf174dba 100644 --- a/src/ast/struct.cc +++ b/src/ast/struct.cc @@ -14,6 +14,8 @@ #include "src/ast/struct.h" +#include + #include "src/ast/struct_block_decoration.h" #include "src/program_builder.h" @@ -24,9 +26,11 @@ namespace ast { Struct::Struct(ProgramID program_id, const Source& source, + Symbol name, StructMemberList members, DecorationList decorations) : Base(program_id, source), + name_(name), members_(std::move(members)), decorations_(std::move(decorations)) { for (auto* mem : members_) { @@ -59,15 +63,16 @@ bool Struct::IsBlockDecorated() const { Struct* Struct::Clone(CloneContext* ctx) const { // Clone arguments outside of create() call to have deterministic ordering auto src = ctx->Clone(source()); + auto n = ctx->Clone(name()); auto mem = ctx->Clone(members()); auto decos = ctx->Clone(decorations()); - return ctx->dst->create(src, mem, decos); + return ctx->dst->create(src, n, mem, decos); } void Struct::to_str(const sem::Info& sem, std::ostream& out, size_t indent) const { - out << "Struct{" << std::endl; + out << "Struct " << name().to_str() << " {" << std::endl; for (auto* deco : decorations_) { make_indent(out, indent + 2); out << "[["; @@ -81,5 +86,13 @@ void Struct::to_str(const sem::Info& sem, out << "}" << std::endl; } +std::string Struct::type_name() const { + return "__struct_" + name().to_str(); +} + +std::string Struct::FriendlyName(const SymbolTable& symbols) const { + return symbols.NameFor(name()); +} + } // namespace ast } // namespace tint diff --git a/src/ast/struct.h b/src/ast/struct.h index b6a0314413..770fb3ebc6 100644 --- a/src/ast/struct.h +++ b/src/ast/struct.h @@ -15,24 +15,28 @@ #ifndef SRC_AST_STRUCT_H_ #define SRC_AST_STRUCT_H_ +#include #include #include "src/ast/decoration.h" #include "src/ast/struct_member.h" +#include "src/ast/type.h" namespace tint { namespace ast { /// A struct statement. -class Struct : public Castable { +class Struct : public Castable { public: /// Create a new struct statement /// @param program_id the identifier of the program that owns this node /// @param source The input source for the import statement + /// @param name The name of the structure /// @param members The struct members /// @param decorations The struct decorations Struct(ProgramID program_id, const Source& source, + Symbol name, StructMemberList members, DecorationList decorations); /// Move constructor @@ -40,6 +44,9 @@ class Struct : public Castable { ~Struct() override; + /// @returns the name of the structure + Symbol name() const { return name_; } + /// @returns the struct decorations const DecorationList& decorations() const { return decorations_; } @@ -68,9 +75,18 @@ class Struct : public Castable { std::ostream& out, size_t indent) const override; + /// @returns the name for the type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + private: Struct(const Struct&) = delete; + Symbol const name_; StructMemberList const members_; DecorationList const decorations_; }; diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc index b7f9b1fd12..6ac527c5c5 100644 --- a/src/ast/struct_test.cc +++ b/src/ast/struct_test.cc @@ -12,19 +12,33 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "src/ast/struct.h" #include "gtest/gtest-spi.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" #include "src/ast/struct_block_decoration.h" #include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" namespace tint { namespace ast { namespace { -using StructTest = TestHelper; +using AstStructTest = TestHelper; -TEST_F(StructTest, Creation) { - auto* s = - create(StructMemberList{Member("a", ty.i32())}, DecorationList{}); +TEST_F(AstStructTest, Creation) { + auto name = Sym("s"); + auto* s = create(name, StructMemberList{Member("a", ty.i32())}, + DecorationList{}); + EXPECT_EQ(s->name(), name); EXPECT_EQ(s->members().size(), 1u); EXPECT_TRUE(s->decorations().empty()); EXPECT_EQ(s->source().range.begin.line, 0u); @@ -33,11 +47,14 @@ TEST_F(StructTest, Creation) { EXPECT_EQ(s->source().range.end.column, 0u); } -TEST_F(StructTest, Creation_WithDecorations) { +TEST_F(AstStructTest, Creation_WithDecorations) { + auto name = Sym("s"); DecorationList decos; decos.push_back(create()); - auto* s = create(StructMemberList{Member("a", ty.i32())}, decos); + auto* s = + create(name, StructMemberList{Member("a", ty.i32())}, decos); + EXPECT_EQ(s->name(), name); EXPECT_EQ(s->members().size(), 1u); ASSERT_EQ(s->decorations().size(), 1u); EXPECT_TRUE(s->decorations()[0]->Is()); @@ -47,13 +64,13 @@ TEST_F(StructTest, Creation_WithDecorations) { EXPECT_EQ(s->source().range.end.column, 0u); } -TEST_F(StructTest, CreationWithSourceAndDecorations) { - DecorationList decos; - decos.push_back(create()); - +TEST_F(AstStructTest, CreationWithSourceAndDecorations) { + auto name = Sym("s"); auto* s = create( Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}}, - StructMemberList{Member("a", ty.i32())}, decos); + name, StructMemberList{Member("a", ty.i32())}, + DecorationList{create()}); + EXPECT_EQ(s->name(), name); EXPECT_EQ(s->members().size(), 1u); ASSERT_EQ(s->decorations().size(), 1u); EXPECT_TRUE(s->decorations()[0]->Is()); @@ -63,60 +80,95 @@ TEST_F(StructTest, CreationWithSourceAndDecorations) { EXPECT_EQ(s->source().range.end.column, 8u); } -TEST_F(StructTest, Assert_Null_StructMember) { +TEST_F(AstStructTest, Assert_Null_StructMember) { EXPECT_FATAL_FAILURE( { ProgramBuilder b; - b.create(StructMemberList{b.Member("a", b.ty.i32()), nullptr}, + b.create(b.Sym("S"), + StructMemberList{b.Member("a", b.ty.i32()), nullptr}, DecorationList{}); }, "internal compiler error"); } -TEST_F(StructTest, Assert_Null_Decoration) { +TEST_F(AstStructTest, Assert_Null_Decoration) { EXPECT_FATAL_FAILURE( { ProgramBuilder b; - b.create(StructMemberList{b.Member("a", b.ty.i32())}, + b.create(b.Sym("S"), + StructMemberList{b.Member("a", b.ty.i32())}, DecorationList{nullptr}); }, "internal compiler error"); } -TEST_F(StructTest, Assert_DifferentProgramID_StructMember) { +TEST_F(AstStructTest, Assert_DifferentProgramID_StructMember) { EXPECT_FATAL_FAILURE( { ProgramBuilder b1; ProgramBuilder b2; - b1.create(StructMemberList{b2.Member("a", b2.ty.i32())}, + b1.create(b2.Sym("S"), + StructMemberList{b2.Member("a", b2.ty.i32())}, DecorationList{}); }, "internal compiler error"); } -TEST_F(StructTest, Assert_DifferentProgramID_Decoration) { +TEST_F(AstStructTest, Assert_DifferentProgramID_Decoration) { EXPECT_FATAL_FAILURE( { ProgramBuilder b1; ProgramBuilder b2; - b1.create(StructMemberList{b1.Member("a", b1.ty.i32())}, + b1.create(b1.Sym("S"), + StructMemberList{b1.Member("a", b1.ty.i32())}, DecorationList{b2.create()}); }, "internal compiler error"); } -TEST_F(StructTest, ToStr) { - DecorationList decos; - decos.push_back(create()); - auto* s = create(StructMemberList{Member("a", ty.i32())}, decos); +TEST_F(AstStructTest, ToStr) { + auto* s = create(Sym("S"), StructMemberList{Member("a", ty.i32())}, + DecorationList{create()}); - EXPECT_EQ(str(s), R"(Struct{ + EXPECT_EQ(str(s), R"(Struct S { [[block]] StructMember{a: __i32} } )"); } +TEST_F(AstStructTest, Is) { + Type* ty = create(Sym("S"), ast::StructMemberList{}, + ast::DecorationList{}); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstStructTest, TypeName) { + auto name = Sym("my_struct"); + auto* s = + create(name, ast::StructMemberList{}, ast::DecorationList{}); + EXPECT_EQ(s->type_name(), "__struct_$1"); +} + +TEST_F(AstStructTest, FriendlyName) { + auto name = Sym("my_struct"); + auto* s = + create(name, ast::StructMemberList{}, ast::DecorationList{}); + EXPECT_EQ(s->FriendlyName(Symbols()), "my_struct"); +} + } // namespace } // namespace ast } // namespace tint diff --git a/src/ast/texture.cc b/src/ast/texture.cc new file mode 100644 index 0000000000..28de192de0 --- /dev/null +++ b/src/ast/texture.cc @@ -0,0 +1,91 @@ +// 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/texture.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Texture); + +namespace tint { +namespace ast { + +std::ostream& operator<<(std::ostream& out, TextureDimension dim) { + switch (dim) { + case TextureDimension::kNone: + out << "None"; + break; + case TextureDimension::k1d: + out << "1d"; + break; + case TextureDimension::k2d: + out << "2d"; + break; + case TextureDimension::k2dArray: + out << "2d_array"; + break; + case TextureDimension::k3d: + out << "3d"; + break; + case TextureDimension::kCube: + out << "cube"; + break; + case TextureDimension::kCubeArray: + out << "cube_array"; + break; + } + return out; +} + +bool IsTextureArray(TextureDimension dim) { + switch (dim) { + case TextureDimension::k2dArray: + case TextureDimension::kCubeArray: + return true; + case TextureDimension::k2d: + case TextureDimension::kNone: + case TextureDimension::k1d: + case TextureDimension::k3d: + case TextureDimension::kCube: + return false; + } + return false; +} + +int NumCoordinateAxes(TextureDimension dim) { + switch (dim) { + case TextureDimension::kNone: + return 0; + case TextureDimension::k1d: + return 1; + case TextureDimension::k2d: + case TextureDimension::k2dArray: + return 2; + case TextureDimension::k3d: + case TextureDimension::kCube: + case TextureDimension::kCubeArray: + return 3; + } + return 0; +} + +Texture::Texture(ProgramID program_id, + const Source& source, + TextureDimension dim) + : Base(program_id, source), dim_(dim) {} + +Texture::Texture(Texture&&) = default; + +Texture::~Texture() = default; + +} // namespace ast +} // namespace tint diff --git a/src/ast/texture.h b/src/ast/texture.h new file mode 100644 index 0000000000..c8c871f4c4 --- /dev/null +++ b/src/ast/texture.h @@ -0,0 +1,81 @@ +// 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_TEXTURE_H_ +#define SRC_AST_TEXTURE_H_ + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// The dimensionality of the texture +enum class TextureDimension { + /// Invalid texture + kNone = -1, + /// 1 dimensional texture + k1d, + /// 2 dimensional texture + k2d, + /// 2 dimensional array texture + k2dArray, + /// 3 dimensional texture + k3d, + /// cube texture + kCube, + /// cube array texture + kCubeArray, +}; + +/// @param out the std::ostream to write to +/// @param dim the TextureDimension +/// @return the std::ostream so calls can be chained +std::ostream& operator<<(std::ostream& out, TextureDimension dim); + +/// @param dim the TextureDimension to query +/// @return true if the given TextureDimension is an array texture +bool IsTextureArray(TextureDimension dim); + +/// Returns the number of axes in the coordinate for a dimensionality. +/// None -> 0 +/// 1D -> 1 +/// 2D, 2DArray -> 2 +/// 3D, Cube, CubeArray -> 3 +/// @param dim the TextureDimension to query +/// @return number of dimensions in a coordinate for the dimensionality +int NumCoordinateAxes(TextureDimension dim); + +/// A texture type. +class Texture : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param dim the dimensionality of the texture + Texture(ProgramID program_id, const Source& source, TextureDimension dim); + /// Move constructor + Texture(Texture&&); + ~Texture() override; + + /// @returns the texture dimension + TextureDimension dim() const { return dim_; } + + private: + TextureDimension const dim_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_TEXTURE_H_ diff --git a/src/ast/texture_test.cc b/src/ast/texture_test.cc new file mode 100644 index 0000000000..10ff52bf39 --- /dev/null +++ b/src/ast/texture_test.cc @@ -0,0 +1,58 @@ +// Copyright 2021 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/texture.h" + +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/u32.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstTextureTypeTest = TestHelper; + +TEST_F(AstTextureTypeTest, IsTextureArray) { + EXPECT_EQ(false, IsTextureArray(TextureDimension::kNone)); + EXPECT_EQ(false, IsTextureArray(TextureDimension::k1d)); + EXPECT_EQ(false, IsTextureArray(TextureDimension::k2d)); + EXPECT_EQ(true, IsTextureArray(TextureDimension::k2dArray)); + EXPECT_EQ(false, IsTextureArray(TextureDimension::k3d)); + EXPECT_EQ(false, IsTextureArray(TextureDimension::kCube)); + EXPECT_EQ(true, IsTextureArray(TextureDimension::kCubeArray)); +} + +TEST_F(AstTextureTypeTest, NumCoordinateAxes) { + EXPECT_EQ(0, NumCoordinateAxes(TextureDimension::kNone)); + EXPECT_EQ(1, NumCoordinateAxes(TextureDimension::k1d)); + EXPECT_EQ(2, NumCoordinateAxes(TextureDimension::k2d)); + EXPECT_EQ(2, NumCoordinateAxes(TextureDimension::k2dArray)); + EXPECT_EQ(3, NumCoordinateAxes(TextureDimension::k3d)); + EXPECT_EQ(3, NumCoordinateAxes(TextureDimension::kCube)); + EXPECT_EQ(3, NumCoordinateAxes(TextureDimension::kCubeArray)); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/type.h b/src/ast/type.h new file mode 100644 index 0000000000..cd0bc0f212 --- /dev/null +++ b/src/ast/type.h @@ -0,0 +1,124 @@ +// 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_H_ +#define SRC_AST_TYPE_H_ + +#include + +#include "src/ast/node.h" +#include "src/clone_context.h" + +namespace tint { + +// Forward declarations +class ProgramBuilder; +class SymbolTable; + +namespace ast { + +/// Base class for a type in the system +class Type : public Castable { + public: + /// Move constructor + Type(Type&&); + ~Type() override; + + /// @returns the name for this type. The type name is unique over all types. + virtual std::string type_name() const = 0; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + virtual std::string FriendlyName(const SymbolTable& symbols) const = 0; + + /// @returns the pointee type if this is a pointer, `this` otherwise + Type* UnwrapPtrIfNeeded(); + + /// @returns the most deeply nested aliased type if this is an alias, `this` + /// otherwise + Type* UnwrapAliasIfNeeded(); + + /// Removes all levels of aliasing and access control. + /// This is just enough to assist with WGSL translation + /// in that you want see through one level of pointer to get from an + /// identifier-like expression as an l-value to its corresponding r-value, + /// plus see through the wrappers on either side. + /// @returns the completely unaliased type. + Type* UnwrapIfNeeded(); + + /// Returns the type found after: + /// - removing all layers of aliasing and access control if they exist, then + /// - removing the pointer, if it exists, then + /// - removing all further layers of aliasing or access control, if they exist + /// @returns the unwrapped type + Type* UnwrapAll(); + + /// @returns true if this type is a scalar + bool is_scalar() const; + /// @returns true if this type is a float scalar + bool is_float_scalar() const; + /// @returns true if this type is a float matrix + bool is_float_matrix() const; + /// @returns true if this type is a float vector + bool is_float_vector() const; + /// @returns true if this type is a float scalar or vector + bool is_float_scalar_or_vector() const; + /// @returns true if this type is a float scalar or vector or matrix + bool is_float_scalar_or_vector_or_matrix() const; + /// @returns true if this type is an integer scalar + bool is_integer_scalar() const; + /// @returns true if this type is a signed integer vector + bool is_signed_integer_vector() const; + /// @returns true if this type is an unsigned vector + bool is_unsigned_integer_vector() const; + /// @returns true if this type is an unsigned scalar or vector + bool is_unsigned_scalar_or_vector() const; + /// @returns true if this type is a signed scalar or vector + bool is_signed_scalar_or_vector() const; + /// @returns true if this type is an integer scalar or vector + bool is_integer_scalar_or_vector() const; + /// @returns true if this type is a boolean vector + bool is_bool_vector() const; + /// @returns true if this type is boolean scalar or vector + bool is_bool_scalar_or_vector() const; + /// @returns true if this type is a handle type + bool is_handle() const; + + /// Writes a representation of the node to the output stream + /// @param sem the semantic info for the program + /// @param out the stream to write to + /// @param indent number of spaces to indent the node when writing + void to_str(const sem::Info& sem, + std::ostream& out, + size_t indent) const override; + + protected: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + Type(ProgramID program_id, const Source& source); +}; + +/// @returns the ProgramID of the given type. +inline ProgramID ProgramIDOf(const Type*) { + /// TODO(crbug.com/tint/724): Actually implement this once we split the `type` + /// namespace into ast::Type and sem::Type. + return ProgramID(); +} + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_TYPE_H_ diff --git a/src/ast/u32.cc b/src/ast/u32.cc new file mode 100644 index 0000000000..8a533c1f46 --- /dev/null +++ b/src/ast/u32.cc @@ -0,0 +1,45 @@ +// 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/u32.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::U32); + +namespace tint { +namespace ast { + +U32::U32(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +U32::~U32() = default; + +U32::U32(U32&&) = default; + +std::string U32::type_name() const { + return "__u32"; +} + +std::string U32::FriendlyName(const SymbolTable&) const { + return "u32"; +} + +U32* U32::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/u32.h b/src/ast/u32.h new file mode 100644 index 0000000000..22d39599ce --- /dev/null +++ b/src/ast/u32.h @@ -0,0 +1,53 @@ +// 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_U32_H_ +#define SRC_AST_U32_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A unsigned int 32 type. +class U32 : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + U32(ProgramID program_id, const Source& source); + /// Move constructor + U32(U32&&); + ~U32() override; + + /// @returns the name for th type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + U32* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_U32_H_ diff --git a/src/ast/u32_test.cc b/src/ast/u32_test.cc new file mode 100644 index 0000000000..94deea62ef --- /dev/null +++ b/src/ast/u32_test.cc @@ -0,0 +1,66 @@ +// 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/u32.h" + +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/vector.h" + +namespace tint { +namespace ast { +namespace { + +using AstU32Test = TestHelper; + +TEST_F(AstU32Test, Is) { + Type* ty = create(); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); + EXPECT_FALSE(ty->Is()); +} + +TEST_F(AstU32Test, TypeName) { + auto* u = create(); + EXPECT_EQ(u->type_name(), "__u32"); +} + +TEST_F(AstU32Test, FriendlyName) { + auto* u = create(); + EXPECT_EQ(u->FriendlyName(Symbols()), "u32"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/vector.cc b/src/ast/vector.cc new file mode 100644 index 0000000000..60e52a39e4 --- /dev/null +++ b/src/ast/vector.cc @@ -0,0 +1,55 @@ +// 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/vector.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Vector); + +namespace tint { +namespace ast { + +Vector::Vector(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t size) + : Base(program_id, source), subtype_(subtype), size_(size) { + TINT_ASSERT(size_ > 1); + TINT_ASSERT(size_ < 5); +} + +Vector::Vector(Vector&&) = default; + +Vector::~Vector() = default; + +std::string Vector::type_name() const { + return "__vec_" + std::to_string(size_) + subtype_->type_name(); +} + +std::string Vector::FriendlyName(const SymbolTable& symbols) const { + std::ostringstream out; + out << "vec" << size_ << "<" << subtype_->FriendlyName(symbols) << ">"; + return out.str(); +} + +Vector* Vector::Clone(CloneContext* ctx) const { + // Clone arguments outside of create() call to have deterministic ordering + auto src = ctx->Clone(source()); + auto* ty = ctx->Clone(type()); + return ctx->dst->create(src, ty, size_); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/vector.h b/src/ast/vector.h new file mode 100644 index 0000000000..13e7cada49 --- /dev/null +++ b/src/ast/vector.h @@ -0,0 +1,67 @@ +// 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_VECTOR_H_ +#define SRC_AST_VECTOR_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A vector type. +class Vector : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + /// @param subtype the vector element type + /// @param size the number of elements in the vector + Vector(ProgramID program_id, + const Source& source, + Type* subtype, + uint32_t size); + /// Move constructor + Vector(Vector&&); + ~Vector() override; + + /// @returns the type of the vector elements + Type* type() const { return subtype_; } + /// @returns the size of the vector + uint32_t size() const { return size_; } + + /// @returns the name for th type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Vector* Clone(CloneContext* ctx) const override; + + private: + Type* const subtype_; + uint32_t const size_; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_VECTOR_H_ diff --git a/src/ast/vector_test.cc b/src/ast/vector_test.cc new file mode 100644 index 0000000000..940cdc33a4 --- /dev/null +++ b/src/ast/vector_test.cc @@ -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. + +#include "src/ast/vector.h" +#include "src/ast/access_control.h" +#include "src/ast/alias.h" +#include "src/ast/array.h" +#include "src/ast/bool.h" +#include "src/ast/f32.h" +#include "src/ast/i32.h" +#include "src/ast/matrix.h" +#include "src/ast/pointer.h" +#include "src/ast/sampler.h" +#include "src/ast/struct.h" +#include "src/ast/test_helper.h" +#include "src/ast/texture.h" +#include "src/ast/u32.h" + +namespace tint { +namespace ast { +namespace { + +using AstVectorTest = TestHelper; + +TEST_F(AstVectorTest, Creation) { + auto* i32 = create(); + auto* v = create(i32, 2); + EXPECT_EQ(v->type(), i32); + EXPECT_EQ(v->size(), 2u); +} + +TEST_F(AstVectorTest, Is) { + auto* i32 = create(); + Type* ty = create(i32, 4); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_FALSE(ty->Is()); + EXPECT_TRUE(ty->Is()); +} + +TEST_F(AstVectorTest, TypeName) { + auto* i32 = create(); + auto* v = create(i32, 3); + EXPECT_EQ(v->type_name(), "__vec_3__i32"); +} + +TEST_F(AstVectorTest, FriendlyName) { + auto* v = ty.vec3(); + EXPECT_EQ(v->FriendlyName(Symbols()), "vec3"); +} + +} // namespace +} // namespace ast +} // namespace tint diff --git a/src/ast/void.cc b/src/ast/void.cc new file mode 100644 index 0000000000..5591cebb2c --- /dev/null +++ b/src/ast/void.cc @@ -0,0 +1,45 @@ +// 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/void.h" + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Void); + +namespace tint { +namespace ast { + +Void::Void(ProgramID program_id, const Source& source) + : Base(program_id, source) {} + +Void::Void(Void&&) = default; + +Void::~Void() = default; + +std::string Void::type_name() const { + return "__void"; +} + +std::string Void::FriendlyName(const SymbolTable&) const { + return "void"; +} + +Void* Void::Clone(CloneContext* ctx) const { + auto src = ctx->Clone(source()); + return ctx->dst->create(src); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/void.h b/src/ast/void.h new file mode 100644 index 0000000000..3ed79b0347 --- /dev/null +++ b/src/ast/void.h @@ -0,0 +1,53 @@ +// 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_VOID_H_ +#define SRC_AST_VOID_H_ + +#include + +#include "src/ast/type.h" + +namespace tint { +namespace ast { + +/// A void type +class Void : public Castable { + public: + /// Constructor + /// @param program_id the identifier of the program that owns this node + /// @param source the source of this node + Void(ProgramID program_id, const Source& source); + /// Move constructor + Void(Void&&); + ~Void() override; + + /// @returns the name for this type + std::string type_name() const override; + + /// @param symbols the program's symbol table + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName(const SymbolTable& symbols) const override; + + /// Clones this type and all transitive types using the `CloneContext` `ctx`. + /// @param ctx the clone context + /// @return the newly cloned type + Void* Clone(CloneContext* ctx) const override; +}; + +} // namespace ast +} // namespace tint + +#endif // SRC_AST_VOID_H_ diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc index f02f1f3718..68f06836cf 100644 --- a/src/inspector/inspector_test.cc +++ b/src/inspector/inspector_test.cc @@ -225,8 +225,9 @@ class InspectorHelper : public ProgramBuilder { decos.push_back(create()); } - auto* str = create(members, decos); - auto* str_ty = ty.struct_(name, str); + auto sym = Sym(name); + auto* str = create(sym, members, decos); + auto* str_ty = ty.struct_(sym, str); AST().AddConstructedType(str_ty); return str_ty; } @@ -1824,6 +1825,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, NonEntryPointFunc) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, MissingBlockDeco) { ast::DecorationList decos; auto* str = create( + Sym("foo_type"), ast::StructMemberList{Member(StructMemberName(0, ty.i32()), ty.i32())}, decos); diff --git a/src/intrinsic_table.cc b/src/intrinsic_table.cc index db7dc549d5..40d2ef1859 100644 --- a/src/intrinsic_table.cc +++ b/src/intrinsic_table.cc @@ -603,7 +603,7 @@ class SamplerBuilder : public Builder { /// AccessControlBuilder is a Matcher / Builder for AccessControl types class AccessControlBuilder : public Builder { public: - explicit AccessControlBuilder(ast::AccessControl access_control, + explicit AccessControlBuilder(ast::AccessControl::Access access_control, Builder* type) : access_control_(access_control), type_(type) {} @@ -628,7 +628,7 @@ class AccessControlBuilder : public Builder { } private: - ast::AccessControl const access_control_; + ast::AccessControl::Access const access_control_; Builder* const type_; }; @@ -765,7 +765,8 @@ class Impl : public IntrinsicTable { } /// @returns a Matcher / Builder that matches an access control type - Builder* access_control(ast::AccessControl access_control, Builder* type) { + Builder* access_control(ast::AccessControl::Access access_control, + Builder* type) { return matcher_allocator_.Create(access_control, type); } diff --git a/src/program_builder.h b/src/program_builder.h index e5dbe148c2..3e518fcfdd 100644 --- a/src/program_builder.h +++ b/src/program_builder.h @@ -535,7 +535,7 @@ class ProgramBuilder { /// @param access the access control /// @param type the inner type /// @returns the access control qualifier type - sem::AccessControl* access(ast::AccessControl access, + sem::AccessControl* access(ast::AccessControl::Access access, sem::Type* type) const { return builder->create(access, type); } @@ -1185,9 +1185,10 @@ class ProgramBuilder { NAME&& name, ast::StructMemberList members, ast::DecorationList decorations = {}) { - auto* impl = - create(source, std::move(members), std::move(decorations)); - auto* type = ty.struct_(Sym(std::forward(name)), impl); + auto sym = Sym(std::forward(name)); + auto* impl = create(source, sym, std::move(members), + std::move(decorations)); + auto* type = ty.struct_(sym, impl); AST().AddConstructedType(type); return type; } @@ -1202,9 +1203,10 @@ class ProgramBuilder { sem::StructType* Structure(NAME&& name, ast::StructMemberList members, ast::DecorationList decorations = {}) { + auto sym = Sym(std::forward(name)); auto* impl = - create(std::move(members), std::move(decorations)); - auto* type = ty.struct_(Sym(std::forward(name)), impl); + create(sym, std::move(members), std::move(decorations)); + auto* type = ty.struct_(sym, impl); AST().AddConstructedType(type); return type; } diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index 1f9a48e5bf..00e94b6dff 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -1338,7 +1338,8 @@ bool FunctionEmitter::LabelControlFlowConstructs() { if (top->ContainsPos(target0_pos) && top->ContainsPos(target1_pos)) { // Insert a synthetic if-selection - top = push_construct(depth+1, Construct::kIfSelection, header, ct); + top = push_construct(depth + 1, Construct::kIfSelection, header, + ct); } } } diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc index 6e0c6996b1..2870f5aa82 100644 --- a/src/reader/spirv/function_memory_test.cc +++ b/src/reader/spirv/function_memory_test.cc @@ -798,7 +798,7 @@ TEST_F(SpvParserTest, RemapStorageBuffer_TypesAndVarDeclarations) { const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( RTArr -> __array__u32_stride_4 - S Struct{ + Struct S { [[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 87315cadaf..e22c749502 100644 --- a/src/reader/spirv/parser_impl.cc +++ b/src/reader/spirv/parser_impl.cc @@ -551,7 +551,7 @@ Source ParserImpl::GetSourceForInst( if (where == inst_source_.end()) { return {}; } - return Source{where->second }; + return Source{where->second}; } bool ParserImpl::ParseInternalModuleExceptFunctions() { @@ -940,15 +940,16 @@ sem::Type* ParserImpl::ConvertType( return nullptr; } - // Now make the struct. - auto* ast_struct = create(Source{}, std::move(ast_members), - std::move(ast_struct_decorations)); - namer_.SuggestSanitizedName(type_id, "S"); auto name = namer_.GetName(type_id); - auto* result = builder_.create( - builder_.Symbols().Register(name), ast_struct); + + // Now make the struct. + auto sym = builder_.Symbols().Register(name); + auto* ast_struct = create(Source{}, sym, std::move(ast_members), + std::move(ast_struct_decorations)); + + auto* result = builder_.create(sym, ast_struct); id_to_type_[type_id] = result; if (num_non_writable_members == members.size()) { read_only_struct_types_.insert(result); diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc index 5957329a61..5915beb976 100644 --- a/src/reader/spirv/parser_impl_convert_type_test.cc +++ b/src/reader/spirv/parser_impl_convert_type_test.cc @@ -553,7 +553,7 @@ TEST_F(SpvParserTest, ConvertType_StructTwoMembers) { EXPECT_TRUE(type->Is()); Program program = p->program(); - EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct{ + EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct S { StructMember{field0: __u32} StructMember{field1: __f32} } @@ -574,7 +574,7 @@ TEST_F(SpvParserTest, ConvertType_StructWithBlockDecoration) { EXPECT_TRUE(type->Is()); Program program = p->program(); - EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct{ + EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct S { [[block]] StructMember{field0: __u32} } @@ -599,7 +599,7 @@ TEST_F(SpvParserTest, ConvertType_StructWithMemberDecorations) { EXPECT_TRUE(type->Is()); Program program = p->program(); - EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct{ + EXPECT_THAT(program.str(type->As()->impl()), Eq(R"(Struct S { StructMember{[[ offset 0 ]] field0: __f32} StructMember{[[ offset 8 ]] field1: __vec_2__f32} StructMember{[[ offset 16 ]] field2: __mat_2_2__f32} diff --git a/src/reader/spirv/parser_impl_module_var_test.cc b/src/reader/spirv/parser_impl_module_var_test.cc index 220261eb03..b52daa2537 100644 --- a/src/reader/spirv/parser_impl_module_var_test.cc +++ b/src/reader/spirv/parser_impl_module_var_test.cc @@ -1654,7 +1654,7 @@ TEST_F(SpvModuleScopeVarParserTest, EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __u32} StructMember{field1: __f32} @@ -1685,7 +1685,7 @@ TEST_F(SpvModuleScopeVarParserTest, ColMajorDecoration_Dropped) { EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __mat_2_3__f32} } @@ -1714,7 +1714,7 @@ TEST_F(SpvModuleScopeVarParserTest, MatrixStrideDecoration_Dropped) { EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __mat_2_3__f32} } @@ -1763,7 +1763,7 @@ TEST_F(SpvModuleScopeVarParserTest, StorageBuffer_NonWritable_AllMembers) { EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __f32} StructMember{field1: __f32} @@ -1792,7 +1792,7 @@ TEST_F(SpvModuleScopeVarParserTest, StorageBuffer_NonWritable_NotAllMembers) { EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __f32} StructMember{field1: __f32} @@ -1824,7 +1824,7 @@ TEST_F( EXPECT_TRUE(p->error().empty()); const auto module_str = p->program().to_str(); EXPECT_THAT(module_str, HasSubstr(R"( - S Struct{ + Struct S { [[block]] StructMember{field0: __f32} StructMember{field1: __f32} diff --git a/src/reader/spirv/parser_impl_named_types_test.cc b/src/reader/spirv/parser_impl_named_types_test.cc index 9f029d80ea..236693911e 100644 --- a/src/reader/spirv/parser_impl_named_types_test.cc +++ b/src/reader/spirv/parser_impl_named_types_test.cc @@ -29,7 +29,7 @@ TEST_F(SpvParserTest, NamedTypes_AnonStruct) { %s = OpTypeStruct %uint %uint )")); EXPECT_TRUE(p->BuildAndParseInternalModule()); - EXPECT_THAT(p->program().to_str(), HasSubstr("S Struct")); + EXPECT_THAT(p->program().to_str(), HasSubstr("Struct S")); } TEST_F(SpvParserTest, NamedTypes_NamedStruct) { @@ -39,7 +39,7 @@ TEST_F(SpvParserTest, NamedTypes_NamedStruct) { %s = OpTypeStruct %uint %uint )")); EXPECT_TRUE(p->BuildAndParseInternalModule()); - EXPECT_THAT(p->program().to_str(), HasSubstr("mystruct Struct")); + EXPECT_THAT(p->program().to_str(), HasSubstr("Struct mystruct")); } TEST_F(SpvParserTest, NamedTypes_Dup_EmitBoth) { @@ -49,11 +49,11 @@ TEST_F(SpvParserTest, NamedTypes_Dup_EmitBoth) { %s2 = OpTypeStruct %uint %uint )")); EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error(); - EXPECT_THAT(p->program().to_str(), HasSubstr(R"(S Struct{ + EXPECT_THAT(p->program().to_str(), HasSubstr(R"(Struct S { StructMember{field0: __u32} StructMember{field1: __u32} } - S_1 Struct{ + Struct S_1 { StructMember{field0: __u32} StructMember{field1: __u32} })")); diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index d230a958f0..6db1b7e375 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -836,7 +836,7 @@ Expect ParserImpl::expect_variable_ident_decl( return TypedIdentifier{ty, ident.value, ident.source}; } -Expect ParserImpl::expect_access_type() { +Expect ParserImpl::expect_access_type() { auto ident = expect_ident("access_type"); if (ident.errored) return Failure::kErrored; @@ -1134,9 +1134,10 @@ Maybe ParserImpl::struct_decl(ast::DecorationList& decos) { if (body.errored) return Failure::kErrored; + auto sym = builder_.Symbols().Register(name.value); return create( - builder_.Symbols().Register(name.value), - create(source, std::move(body.value), std::move(decos))); + sym, create(source, sym, std::move(body.value), + std::move(decos))); } // struct_body_decl diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index b15fd1660c..a7ae4434aa 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -437,7 +437,7 @@ class ParserImpl { /// Parses an access type identifier, erroring if the next token does not /// match a valid access type name. /// @returns the parsed access control. - Expect expect_access_type(); + Expect expect_access_type(); /// Parses a builtin identifier, erroring if the next token does not match a /// valid builtin name. /// @returns the parsed builtin. diff --git a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc index 327088104b..6719ade560 100644 --- a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc +++ b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc @@ -115,7 +115,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_ParsesWithAccessDeco_Read) { ast::DecorationList decos; decos.push_back(block_deco); - auto* str = create(members, decos); + auto* str = create(Sym("S"), members, decos); auto* s = ty.struct_("S", str); p->register_constructed("S", s); @@ -140,7 +140,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_ParsesWithAccessDeco_ReadWrite) { ast::DecorationList decos; decos.push_back(block_deco); - auto* str = create(members, decos); + auto* str = create(Sym("S"), members, decos); auto* s = ty.struct_("S", str); p->register_constructed("S", s); @@ -165,7 +165,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_MultipleAccessDecoFail) { ast::DecorationList decos; decos.push_back(block_deco); - auto* str = create(members, decos); + auto* str = create(Sym("S"), members, decos); auto* s = ty.struct_("S", str); p->register_constructed("S", s); @@ -187,7 +187,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_MultipleAccessDeco_MultiBlock_Fail) { ast::DecorationList decos; decos.push_back(block_deco); - auto* str = create(members, decos); + auto* str = create(Sym("S"), members, decos); auto* s = ty.struct_("S", str); p->register_constructed("S", s); @@ -225,7 +225,7 @@ TEST_F(ParserImplTest, VariableIdentDecl_NonAccessDecoFail) { ast::DecorationList decos; decos.push_back(block_deco); - auto* str = create(members, decos); + auto* str = create(Sym("S"), members, decos); auto* s = ty.struct_("S", str); p->register_constructed("S", s); diff --git a/src/resolver/decoration_validation_test.cc b/src/resolver/decoration_validation_test.cc index cb4f29f145..b60a95d55c 100644 --- a/src/resolver/decoration_validation_test.cc +++ b/src/resolver/decoration_validation_test.cc @@ -131,7 +131,8 @@ TEST_P(ArrayDecorationTest, IsValid) { ast::DecorationList{createDecoration( Source{{12, 34}}, *this, params.kind)}))}; auto* s = create( - members, ast::DecorationList{create()}); + Sym("mystruct"), members, + ast::DecorationList{create()}); auto* s_ty = ty.struct_("mystruct", s); AST().AddConstructedType(s_ty); @@ -166,7 +167,7 @@ using StructDecorationTest = TestWithParams; TEST_P(StructDecorationTest, IsValid) { auto& params = GetParam(); - auto* s = create(ast::StructMemberList{}, + auto* s = create(Sym("mystruct"), ast::StructMemberList{}, ast::DecorationList{createDecoration( Source{{12, 34}}, *this, params.kind)}); auto* s_ty = ty.struct_("mystruct", s); @@ -207,7 +208,8 @@ TEST_P(StructMemberDecorationTest, IsValid) { Member("a", ty.i32(), ast::DecorationList{ createDecoration(Source{{12, 34}}, *this, params.kind)})}; - auto* s = create(members, ast::DecorationList{}); + auto* s = + create(Sym("mystruct"), members, ast::DecorationList{}); auto* s_ty = ty.struct_("mystruct", s); AST().AddConstructedType(s_ty); diff --git a/src/resolver/resolver_test.cc b/src/resolver/resolver_test.cc index 6ea8536fa5..23bede2732 100644 --- a/src/resolver/resolver_test.cc +++ b/src/resolver/resolver_test.cc @@ -889,6 +889,7 @@ TEST_F(ResolverTest, Function_ReturnStatements) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { auto* strct = create( + Sym("S"), ast::StructMemberList{Member("first_member", ty.i32()), Member("second_member", ty.f32())}, ast::DecorationList{}); @@ -918,6 +919,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { auto* strct = create( + Sym("alias"), ast::StructMemberList{Member("first_member", ty.i32()), Member("second_member", ty.f32())}, ast::DecorationList{}); @@ -999,14 +1001,15 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) { // } // - auto* strctB = - create(ast::StructMemberList{Member("foo", ty.vec4())}, - ast::DecorationList{}); + auto* strctB = create( + Sym("B"), ast::StructMemberList{Member("foo", ty.vec4())}, + ast::DecorationList{}); auto* stB = ty.struct_("B", strctB); sem::Vector vecB(stB, 3); - auto* strctA = create( - ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{}); + auto* strctA = + create(Sym("A"), ast::StructMemberList{Member("mem", &vecB)}, + ast::DecorationList{}); auto* stA = ty.struct_("A", strctA); Global("c", stA, ast::StorageClass::kInput); @@ -1027,6 +1030,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) { TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) { auto* strct = create( + Sym("S"), ast::StructMemberList{Member("first_member", ty.f32()), Member("second_member", ty.f32())}, ast::DecorationList{}); diff --git a/src/resolver/type_validation_test.cc b/src/resolver/type_validation_test.cc index 138efe9d7c..49aeb137f8 100644 --- a/src/resolver/type_validation_test.cc +++ b/src/resolver/type_validation_test.cc @@ -315,7 +315,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLast_Pass) { ast::DecorationList decos; decos.push_back(create()); auto* st = - create(ast::StructMemberList{Member("vf", ty.f32()), + create(Sym("Foo"), + ast::StructMemberList{Member("vf", ty.f32()), Member("rt", ty.array())}, decos); @@ -335,6 +336,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLastNoBlock_Fail) { ast::DecorationList decos; auto* st = create( + Sym("Foo"), ast::StructMemberList{Member("vf", ty.f32()), Member(Source{{12, 34}}, "rt", ty.array())}, decos); @@ -362,7 +364,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) { auto* rt = Member(Source{{12, 34}}, "rt", ty.array()); auto* st = create( - ast::StructMemberList{rt, Member("vf", ty.f32())}, decos); + Sym("Foo"), ast::StructMemberList{rt, Member("vf", ty.f32())}, decos); auto* struct_type = ty.struct_("Foo", st); @@ -438,6 +440,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) { ast::DecorationList decos; decos.push_back(create()); auto* st = create( + Sym("s"), ast::StructMemberList{Member(Source{{12, 34}}, "b", alias), Member("a", ty.u32())}, decos); @@ -467,6 +470,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) { ast::DecorationList decos; decos.push_back(create()); auto* st = create( + Sym("s"), ast::StructMemberList{Member("a", ty.u32()), Member("b", alias)}, decos); auto* struct_type = ty.struct_("s", st); diff --git a/src/sem/access_control_type.cc b/src/sem/access_control_type.cc index 09e9af2ad5..6c3101f5af 100644 --- a/src/sem/access_control_type.cc +++ b/src/sem/access_control_type.cc @@ -21,7 +21,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::AccessControl); namespace tint { namespace sem { -AccessControl::AccessControl(ast::AccessControl access, Type* subtype) +AccessControl::AccessControl(ast::AccessControl::Access access, Type* subtype) : access_(access), subtype_(subtype) { TINT_ASSERT(subtype_); TINT_ASSERT(!subtype_->Is()); diff --git a/src/sem/access_control_type.h b/src/sem/access_control_type.h index 7f6ac3718a..5772970fa3 100644 --- a/src/sem/access_control_type.h +++ b/src/sem/access_control_type.h @@ -29,7 +29,7 @@ class AccessControl : public Castable { /// Constructor /// @param access the access control setting /// @param subtype the access controlled type - AccessControl(ast::AccessControl access, Type* subtype); + AccessControl(ast::AccessControl::Access access, Type* subtype); /// Move constructor AccessControl(AccessControl&&); ~AccessControl() override; @@ -42,7 +42,7 @@ class AccessControl : public Castable { bool IsReadWrite() const { return access_ == ast::AccessControl::kReadWrite; } /// @returns the access control value - ast::AccessControl access_control() const { return access_; } + ast::AccessControl::Access access_control() const { return access_; } /// @returns the subtype type Type* type() const { return subtype_; } @@ -60,7 +60,7 @@ class AccessControl : public Castable { AccessControl* Clone(CloneContext* ctx) const override; private: - ast::AccessControl const access_; + ast::AccessControl::Access const access_; Type* const subtype_; }; diff --git a/src/sem/external_texture_type.h b/src/sem/external_texture_type.h index 8179d9f20c..e91cd00583 100644 --- a/src/sem/external_texture_type.h +++ b/src/sem/external_texture_type.h @@ -21,6 +21,8 @@ namespace tint { namespace sem { + +/// An external texture type class ExternalTexture : public Castable { public: /// Constructor @@ -46,4 +48,5 @@ class ExternalTexture : public Castable { } // namespace sem } // namespace tint + #endif // SRC_SEM_EXTERNAL_TEXTURE_TYPE_H_ diff --git a/src/sem/struct_type_test.cc b/src/sem/struct_type_test.cc index a667cfa2be..0571c88db7 100644 --- a/src/sem/struct_type_test.cc +++ b/src/sem/struct_type_test.cc @@ -23,17 +23,19 @@ namespace { using StructTypeTest = TestHelper; TEST_F(StructTypeTest, Creation) { + auto name = Sym("S"); auto* impl = - create(ast::StructMemberList{}, ast::DecorationList{}); + create(name, ast::StructMemberList{}, ast::DecorationList{}); auto* ptr = impl; - auto* s = ty.struct_("S", impl); + auto* s = ty.struct_(name, impl); EXPECT_EQ(s->impl(), ptr); } TEST_F(StructTypeTest, Is) { + auto name = Sym("S"); auto* impl = - create(ast::StructMemberList{}, ast::DecorationList{}); - auto* s = ty.struct_("S", impl); + create(name, ast::StructMemberList{}, ast::DecorationList{}); + auto* s = ty.struct_(name, impl); sem::Type* ty = s; EXPECT_FALSE(ty->Is()); EXPECT_FALSE(ty->Is()); @@ -51,16 +53,18 @@ TEST_F(StructTypeTest, Is) { } TEST_F(StructTypeTest, TypeName) { + auto name = Sym("my_struct"); auto* impl = - create(ast::StructMemberList{}, ast::DecorationList{}); - auto* s = ty.struct_("my_struct", impl); + create(name, ast::StructMemberList{}, ast::DecorationList{}); + auto* s = ty.struct_(name, impl); EXPECT_EQ(s->type_name(), "__struct_$1"); } TEST_F(StructTypeTest, FriendlyName) { + auto name = Sym("my_struct"); auto* impl = - create(ast::StructMemberList{}, ast::DecorationList{}); - auto* s = ty.struct_("my_struct", impl); + create(name, ast::StructMemberList{}, ast::DecorationList{}); + auto* s = ty.struct_(name, impl); EXPECT_EQ(s->FriendlyName(Symbols()), "my_struct"); } diff --git a/src/transform/binding_remapper.cc b/src/transform/binding_remapper.cc index 2dc14a34d2..1a19e782a9 100644 --- a/src/transform/binding_remapper.cc +++ b/src/transform/binding_remapper.cc @@ -63,7 +63,7 @@ Output BindingRemapper::Run(const Program* in, const DataMap& datamap) { // Replace any access controls. auto ac_it = remappings->access_controls.find(from); if (ac_it != remappings->access_controls.end()) { - ast::AccessControl ac = ac_it->second; + ast::AccessControl::Access ac = ac_it->second; auto* ty = in->Sem().Get(var)->Type(); sem::Type* inner_ty = nullptr; if (auto* old_ac = ty->As()) { diff --git a/src/transform/binding_remapper.h b/src/transform/binding_remapper.h index b80d82373f..4b6ef83cbc 100644 --- a/src/transform/binding_remapper.h +++ b/src/transform/binding_remapper.h @@ -32,7 +32,8 @@ class BindingRemapper : public Transform { using BindingPoints = std::unordered_map; /// AccessControls is a map of old binding point to new access control - using AccessControls = std::unordered_map; + using AccessControls = + std::unordered_map; /// Remappings is consumed by the BindingRemapper transform. /// Data holds information about shader usage and constant buffer offsets. diff --git a/src/transform/canonicalize_entry_point_io.cc b/src/transform/canonicalize_entry_point_io.cc index 90d72b1406..55b86d1de7 100644 --- a/src/transform/canonicalize_entry_point_io.cc +++ b/src/transform/canonicalize_entry_point_io.cc @@ -81,10 +81,11 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) { } // Redeclare the struct. + auto new_struct_name = ctx.Clone(struct_ty->symbol()); auto* new_struct = ctx.dst->create( - ctx.Clone(struct_ty->symbol()), - ctx.dst->create( - new_struct_members, ctx.Clone(struct_ty->impl()->decorations()))); + new_struct_name, ctx.dst->create( + new_struct_name, new_struct_members, + ctx.Clone(struct_ty->impl()->decorations()))); ctx.Replace(struct_ty, new_struct); } } @@ -174,9 +175,10 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) { StructMemberComparator); // Create the new struct type. + auto in_struct_name = ctx.dst->Symbols().New(); auto* in_struct = ctx.dst->create( - ctx.dst->Symbols().New(), - ctx.dst->create(new_struct_members, + in_struct_name, + ctx.dst->create(in_struct_name, new_struct_members, ast::DecorationList{})); ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func, in_struct); @@ -220,9 +222,10 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap&) { StructMemberComparator); // Create the new struct type. + auto out_struct_name = ctx.dst->Symbols().New(); auto* out_struct = ctx.dst->create( - ctx.dst->Symbols().New(), - ctx.dst->create(new_struct_members, + out_struct_name, + ctx.dst->create(out_struct_name, new_struct_members, ast::DecorationList{})); ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func, out_struct); new_ret_type = out_struct; diff --git a/src/transform/spirv.cc b/src/transform/spirv.cc index e16a22a672..09d7324e2d 100644 --- a/src/transform/spirv.cc +++ b/src/transform/spirv.cc @@ -126,10 +126,11 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const { } // Redeclare the struct. + auto new_struct_name = ctx.Clone(struct_ty->symbol()); auto* new_struct = ctx.dst->create( - ctx.Clone(struct_ty->symbol()), - ctx.dst->create( - new_struct_members, ctx.Clone(struct_ty->impl()->decorations()))); + new_struct_name, ctx.dst->create( + new_struct_name, new_struct_members, + ctx.Clone(struct_ty->impl()->decorations()))); ctx.Replace(struct_ty, new_struct); } } diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index de53041086..610f9b5f28 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -3145,7 +3145,7 @@ bool Builder::GeneratePointerType(sem::Pointer* ptr, const Operand& result) { } bool Builder::GenerateStructType(sem::StructType* struct_type, - ast::AccessControl access_control, + ast::AccessControl::Access access_control, const Operand& result) { auto struct_id = result.to_i(); auto* impl = struct_type->impl(); diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h index 5f44e0f5d6..bea880da53 100644 --- a/src/writer/spirv/builder.h +++ b/src/writer/spirv/builder.h @@ -450,7 +450,7 @@ class Builder { /// @param result the result operand /// @returns true if the vector was successfully generated bool GenerateStructType(sem::StructType* struct_type, - ast::AccessControl access_control, + ast::AccessControl::Access access_control, const Operand& result); /// Generates a struct member /// @param struct_id the id of the parent structure diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc index 167fef7e5a..0ac4460136 100644 --- a/src/writer/wgsl/generator_impl_type_test.cc +++ b/src/writer/wgsl/generator_impl_type_test.cc @@ -436,7 +436,7 @@ INSTANTIATE_TEST_SUITE_P(WgslGeneratorImplTest, struct StorageTextureData { sem::ImageFormat fmt; sem::TextureDimension dim; - ast::AccessControl access; + ast::AccessControl::Access access; const char* name; }; inline std::ostream& operator<<(std::ostream& out, StorageTextureData data) { diff --git a/test/BUILD.gn b/test/BUILD.gn index ba2a815a64..2b19a60d98 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -138,14 +138,18 @@ tint_unittests_source_set("tint_unittests_core_sem_src") { tint_unittests_source_set("tint_unittests_core_src") { sources = [ + "../src/ast/access_control_test.cc", "../src/ast/access_decoration_test.cc", + "../src/ast/alias_test.cc", "../src/ast/array_accessor_expression_test.cc", + "../src/ast/array_test.cc", "../src/ast/assignment_statement_test.cc", "../src/ast/binary_expression_test.cc", "../src/ast/binding_decoration_test.cc", "../src/ast/bitcast_expression_test.cc", "../src/ast/block_statement_test.cc", "../src/ast/bool_literal_test.cc", + "../src/ast/bool_test.cc", "../src/ast/break_statement_test.cc", "../src/ast/builtin_decoration_test.cc", "../src/ast/call_expression_test.cc", @@ -153,12 +157,15 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/ast/case_statement_test.cc", "../src/ast/constant_id_decoration_test.cc", "../src/ast/continue_statement_test.cc", + "../src/ast/depth_texture_test.cc", "../src/ast/discard_statement_test.cc", "../src/ast/else_statement_test.cc", + "../src/ast/f32_test.cc", "../src/ast/fallthrough_statement_test.cc", "../src/ast/float_literal_test.cc", "../src/ast/function_test.cc", "../src/ast/group_decoration_test.cc", + "../src/ast/i32_test.cc", "../src/ast/identifier_expression_test.cc", "../src/ast/if_statement_test.cc", "../src/ast/int_literal_test.cc", @@ -166,13 +173,19 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/ast/intrinsic_texture_helper_test.h", "../src/ast/location_decoration_test.cc", "../src/ast/loop_statement_test.cc", + "../src/ast/matrix_test.cc", "../src/ast/member_accessor_expression_test.cc", "../src/ast/module_clone_test.cc", "../src/ast/module_test.cc", + "../src/ast/multisampled_texture_test.cc", + "../src/ast/pointer_test.cc", "../src/ast/return_statement_test.cc", + "../src/ast/sampled_texture_test.cc", + "../src/ast/sampler_test.cc", "../src/ast/scalar_constructor_expression_test.cc", "../src/ast/sint_literal_test.cc", "../src/ast/stage_decoration_test.cc", + "../src/ast/storage_texture_test.cc", "../src/ast/stride_decoration_test.cc", "../src/ast/struct_member_align_decoration_test.cc", "../src/ast/struct_member_offset_decoration_test.cc", @@ -181,11 +194,14 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/ast/struct_test.cc", "../src/ast/switch_statement_test.cc", "../src/ast/test_helper.h", + "../src/ast/texture_test.cc", "../src/ast/type_constructor_expression_test.cc", + "../src/ast/u32_test.cc", "../src/ast/uint_literal_test.cc", "../src/ast/unary_op_expression_test.cc", "../src/ast/variable_decl_statement_test.cc", "../src/ast/variable_test.cc", + "../src/ast/vector_test.cc", "../src/ast/workgroup_decoration_test.cc", "../src/block_allocator_test.cc", "../src/castable_test.cc", @@ -208,9 +224,9 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/resolver/intrinsic_test.cc", "../src/resolver/is_host_shareable_test.cc", "../src/resolver/is_storeable_test.cc", - "../src/resolver/resolver_test.cc", "../src/resolver/resolver_test_helper.cc", "../src/resolver/resolver_test_helper.h", + "../src/resolver/resolver_test.cc", "../src/resolver/storage_class_validation_test.cc", "../src/resolver/struct_layout_test.cc", "../src/resolver/struct_pipeline_stage_use_test.cc", @@ -253,11 +269,12 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/transform/vertex_pulling_test.cc", "../src/utils/command.h", "../src/utils/command_test.cc", + "../src/utils/command.h", "../src/utils/get_or_create_test.cc", "../src/utils/hash_test.cc", "../src/utils/math_test.cc", - "../src/utils/tmpfile.h", "../src/utils/tmpfile_test.cc", + "../src/utils/tmpfile.h", "../src/utils/unique_vector_test.cc", "../src/writer/append_vector_test.cc", "../src/writer/float_to_string_test.cc",