ast: Add type nodes
Copy all of the type classes from src/type into ast.
Required the merging of:
* type::Struct into the existing ast::Struct - ast::Struct now has a name.
* type::AccessControl into the existing ast::AccessControl enumerator - The old ast::AccessControl enumerator is now ast::AccessControl::Access
Bug: tint:724
Change-Id: Ibb950036ed551ec769c6d3d2c8fb411809cf6931
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48383
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/fuzzers/tint_ast_clone_fuzzer.cc b/fuzzers/tint_ast_clone_fuzzer.cc
index f773aa4..fdb83c1 100644
--- a/fuzzers/tint_ast_clone_fuzzer.cc
+++ b/fuzzers/tint_ast_clone_fuzzer.cc
@@ -77,7 +77,7 @@
for (auto* src_node : src.ASTNodes().Objects()) {
src_nodes.emplace(src_node);
}
- std::unordered_set<tint::type::Type*> src_types;
+ std::unordered_set<tint::sem::Type*> src_types;
for (auto* src_type : src.Types()) {
src_types.emplace(src_type);
}
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 1914280..2a940b6 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -284,8 +284,12 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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 @@
"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 cac6fbe..9e6de7b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,8 +42,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 9a70a64..0c1c1d3 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(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<AccessControl>(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 4539cd1..106b31e 100644
--- a/src/ast/access_control.h
+++ b/src/ast/access_control.h
@@ -16,24 +16,73 @@
#define SRC_AST_ACCESS_CONTROL_H_
#include <ostream>
+#include <string>
+
+#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<AccessControl, Type> {
+ 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 0000000..c03d833
--- /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<U32>();
+ auto* a = create<AccessControl>(AccessControl::kReadWrite, u32);
+ EXPECT_TRUE(a->IsReadWrite());
+ EXPECT_EQ(a->type(), u32);
+}
+
+TEST_F(AstAccessControlTest, Is) {
+ auto* i32 = create<I32>();
+ Type* ty = create<AccessControl>(AccessControl::kReadOnly, i32);
+ EXPECT_TRUE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstAccessControlTest, AccessRead) {
+ auto* i32 = create<I32>();
+ auto* ac = create<AccessControl>(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<I32>();
+ auto* ac = create<AccessControl>(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<I32>();
+ auto* ac = create<AccessControl>(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<I32>();
+ auto* ac = create<AccessControl>(AccessControl::kReadOnly, i32);
+ EXPECT_EQ(ac->FriendlyName(Symbols()), "[[access(read)]] i32");
+}
+
+TEST_F(AstAccessControlTest, FriendlyNameWriteOnly) {
+ auto* i32 = create<I32>();
+ auto* ac = create<AccessControl>(AccessControl::kWriteOnly, i32);
+ EXPECT_EQ(ac->FriendlyName(Symbols()), "[[access(write)]] i32");
+}
+
+TEST_F(AstAccessControlTest, FriendlyNameReadWrite) {
+ auto* i32 = create<I32>();
+ auto* ac = create<AccessControl>(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 ad5be5b..e00ace6 100644
--- a/src/ast/access_decoration.cc
+++ b/src/ast/access_decoration.cc
@@ -23,7 +23,7 @@
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 0ad41bf..894bb69 100644
--- a/src/ast/access_decoration.h
+++ b/src/ast/access_decoration.h
@@ -30,11 +30,11 @@
/// @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 @@
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 0000000..80e5957
--- /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<Alias>(src, sym, ty);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/alias.h b/src/ast/alias.h
new file mode 100644
index 0000000..d95387d
--- /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 <string>
+
+#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<Alias, Type> {
+ 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 0000000..ae36314
--- /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<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+ EXPECT_EQ(a->symbol(), Symbol(1, ID()));
+ EXPECT_EQ(a->type(), u32);
+}
+
+TEST_F(AstAliasTest, Is) {
+ Type* ty = create<Alias>(Sym("a"), create<I32>());
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_TRUE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstAliasTest, TypeName) {
+ auto* at = create<Alias>(Sym("Particle"), create<I32>());
+ EXPECT_EQ(at->type_name(), "__alias_$1__i32");
+}
+
+TEST_F(AstAliasTest, FriendlyName) {
+ auto* at = create<Alias>(Sym("Particle"), create<I32>());
+ EXPECT_EQ(at->FriendlyName(Symbols()), "Particle");
+}
+
+TEST_F(AstAliasTest, UnwrapIfNeeded_Alias) {
+ auto* u32 = create<U32>();
+ auto* a = create<Alias>(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<U32>();
+ auto* ac = create<AccessControl>(AccessControl::kReadOnly, u32);
+ EXPECT_EQ(ac->type(), u32);
+ EXPECT_EQ(ac->UnwrapIfNeeded(), u32);
+}
+
+TEST_F(AstAliasTest, UnwrapIfNeeded_MultiLevel) {
+ auto* u32 = create<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+ auto* aa = create<Alias>(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<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+
+ auto* ac = create<AccessControl>(AccessControl::kReadWrite, a);
+ EXPECT_EQ(ac->type(), a);
+ EXPECT_EQ(ac->UnwrapIfNeeded(), u32);
+}
+
+TEST_F(AstAliasTest, UnwrapAll_TwiceAliasPointerTwiceAlias) {
+ auto* u32 = create<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+ auto* aa = create<Alias>(Sym("aa_type"), a);
+ auto* paa = create<Pointer>(aa, StorageClass::kUniform);
+ auto* apaa = create<Alias>(Sym("paa_type"), paa);
+ auto* aapaa = create<Alias>(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<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+ auto* aa = create<Alias>(Sym("aa_type"), a);
+
+ auto* paa = create<Pointer>(aa, StorageClass::kUniform);
+ auto* ppaa = create<Pointer>(paa, StorageClass::kUniform);
+ auto* appaa = create<Alias>(Sym("appaa_type"), ppaa);
+ EXPECT_EQ(appaa->UnwrapAll(), paa);
+}
+
+TEST_F(AstAliasTest, UnwrapAll_SecondNonConsecutivePointerBlocksUnrapping) {
+ auto* u32 = create<U32>();
+ auto* a = create<Alias>(Sym("a_type"), u32);
+ auto* aa = create<Alias>(Sym("aa_type"), a);
+ auto* paa = create<Pointer>(aa, StorageClass::kUniform);
+
+ auto* apaa = create<Alias>(Sym("apaa_type"), paa);
+ auto* aapaa = create<Alias>(Sym("aapaa_type"), apaa);
+ auto* paapaa = create<Pointer>(aapaa, StorageClass::kUniform);
+ auto* apaapaa = create<Alias>(Sym("apaapaa_type"), paapaa);
+
+ EXPECT_EQ(apaapaa->UnwrapAll(), paa);
+}
+
+TEST_F(AstAliasTest, UnwrapAll_AccessControlPointer) {
+ auto* u32 = create<U32>();
+ auto* a = create<AccessControl>(AccessControl::kReadOnly, u32);
+ auto* pa = create<Pointer>(a, StorageClass::kUniform);
+ EXPECT_EQ(pa->type(), a);
+ EXPECT_EQ(pa->UnwrapAll(), u32);
+}
+
+TEST_F(AstAliasTest, UnwrapAll_PointerAccessControl) {
+ auto* u32 = create<U32>();
+ auto* p = create<Pointer>(u32, StorageClass::kUniform);
+ auto* a = create<AccessControl>(AccessControl::kReadOnly, p);
+
+ EXPECT_EQ(a->type(), p);
+ EXPECT_EQ(a->UnwrapAll(), u32);
+}
+
+TEST_F(AstAliasTest, UnwrapAliasIfNeeded) {
+ auto* f32 = create<F32>();
+ auto* alias1 = create<Alias>(Sym("alias1"), f32);
+ auto* alias2 = create<Alias>(Sym("alias2"), alias1);
+ auto* alias3 = create<Alias>(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 0000000..96ac1de
--- /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 <cmath>
+
+#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<ast::StrideDecoration>()) {
+ 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<ast::StrideDecoration>()) {
+ 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<Array>(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 0000000..c5ba1b8
--- /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 <string>
+
+#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<Array, Type> {
+ 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 0000000..9619bdf
--- /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<U32>();
+ auto* arr = create<Array>(u32, 3, DecorationList{});
+ EXPECT_EQ(arr->type(), u32);
+ EXPECT_EQ(arr->size(), 3u);
+ EXPECT_TRUE(arr->Is<Array>());
+ EXPECT_FALSE(arr->IsRuntimeArray());
+}
+
+TEST_F(AstArrayTest, CreateRuntimeArray) {
+ auto* u32 = create<U32>();
+ auto* arr = create<Array>(u32, 0, DecorationList{});
+ EXPECT_EQ(arr->type(), u32);
+ EXPECT_EQ(arr->size(), 0u);
+ EXPECT_TRUE(arr->Is<Array>());
+ EXPECT_TRUE(arr->IsRuntimeArray());
+}
+
+TEST_F(AstArrayTest, Is) {
+ auto* i32 = create<I32>();
+ Type* ty = create<Array>(i32, 3, DecorationList{});
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_TRUE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstArrayTest, TypeName) {
+ auto* i32 = create<I32>();
+ auto* arr = create<Array>(i32, 0, DecorationList{});
+ EXPECT_EQ(arr->type_name(), "__array__i32");
+}
+
+TEST_F(AstArrayTest, FriendlyNameRuntimeSized) {
+ auto* i32 = create<I32>();
+ auto* arr = create<Array>(i32, 0, DecorationList{});
+ EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32>");
+}
+
+TEST_F(AstArrayTest, FriendlyNameStaticSized) {
+ auto* i32 = create<I32>();
+ auto* arr = create<Array>(i32, 5, DecorationList{});
+ EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, 5>");
+}
+
+TEST_F(AstArrayTest, FriendlyNameWithStride) {
+ auto* i32 = create<I32>();
+ auto* arr =
+ create<Array>(i32, 5, DecorationList{create<StrideDecoration>(32)});
+ EXPECT_EQ(arr->FriendlyName(Symbols()), "[[stride(32)]] array<i32, 5>");
+}
+
+TEST_F(AstArrayTest, TypeName_RuntimeArray) {
+ auto* i32 = create<I32>();
+ auto* arr = create<Array>(i32, 3, DecorationList{});
+ EXPECT_EQ(arr->type_name(), "__array__i32_3");
+}
+
+TEST_F(AstArrayTest, TypeName_WithStride) {
+ auto* i32 = create<I32>();
+ auto* arr =
+ create<Array>(i32, 3, DecorationList{create<StrideDecoration>(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 0000000..766b7a5
--- /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<Pointer>()) {
+ return ptr->type();
+ }
+ return this;
+}
+
+Type* Type::UnwrapAliasIfNeeded() {
+ Type* unwrapped = this;
+ while (auto* ptr = unwrapped->As<Alias>()) {
+ unwrapped = ptr->type();
+ }
+ return unwrapped;
+}
+
+Type* Type::UnwrapIfNeeded() {
+ auto* where = this;
+ while (true) {
+ if (auto* alias = where->As<Alias>()) {
+ where = alias->type();
+ } else if (auto* access = where->As<AccessControl>()) {
+ where = access->type();
+ } else {
+ break;
+ }
+ }
+ return where;
+}
+
+Type* Type::UnwrapAll() {
+ return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
+}
+
+bool Type::is_scalar() const {
+ return IsAnyOf<F32, U32, I32, Bool>();
+}
+
+bool Type::is_float_scalar() const {
+ return Is<F32>();
+}
+
+bool Type::is_float_matrix() const {
+ return Is<Matrix>(
+ [](const Matrix* m) { return m->type()->is_float_scalar(); });
+}
+
+bool Type::is_float_vector() const {
+ return Is<Vector>(
+ [](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<U32, I32>();
+}
+
+bool Type::is_unsigned_integer_vector() const {
+ return Is<Vector>([](const Vector* v) { return v->type()->Is<U32>(); });
+}
+
+bool Type::is_signed_integer_vector() const {
+ return Is<Vector>([](const Vector* v) { return v->type()->Is<I32>(); });
+}
+
+bool Type::is_unsigned_scalar_or_vector() const {
+ return Is<U32>() || is_unsigned_integer_vector();
+}
+
+bool Type::is_signed_scalar_or_vector() const {
+ return Is<I32>() || 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<Vector>([](const Vector* v) { return v->type()->Is<Bool>(); });
+}
+
+bool Type::is_bool_scalar_or_vector() const {
+ return Is<Bool>() || is_bool_vector();
+}
+
+bool Type::is_handle() const {
+ return IsAnyOf<Sampler, Texture>();
+}
+
+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 0000000..d212812
--- /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<Bool>(src);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/bool.h b/src/ast/bool.h
new file mode 100644
index 0000000..ad5b858
--- /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 <string>
+
+#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<Bool, Type> {
+ 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 0000000..3d2b2a8
--- /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<Bool>();
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_TRUE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstBoolTest, TypeName) {
+ auto* b = create<Bool>();
+ EXPECT_EQ(b->type_name(), "__bool");
+}
+
+TEST_F(AstBoolTest, FriendlyName) {
+ auto* b = create<Bool>();
+ 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 0000000..b669113
--- /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<DepthTexture>(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 0000000..7fe82e5
--- /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 <string>
+
+#include "src/ast/texture.h"
+
+namespace tint {
+namespace ast {
+
+/// A depth texture type.
+class DepthTexture : public Castable<DepthTexture, Texture> {
+ 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 0000000..a682d9b
--- /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<DepthTexture>(TextureDimension::kCube);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_TRUE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstDepthTextureTest, IsTexture) {
+ Texture* ty = create<DepthTexture>(TextureDimension::kCube);
+ EXPECT_TRUE(ty->Is<DepthTexture>());
+ EXPECT_FALSE(ty->Is<SampledTexture>());
+ EXPECT_FALSE(ty->Is<StorageTexture>());
+}
+
+TEST_F(AstDepthTextureTest, Dim) {
+ auto* d = create<DepthTexture>(TextureDimension::kCube);
+ EXPECT_EQ(d->dim(), TextureDimension::kCube);
+}
+
+TEST_F(AstDepthTextureTest, TypeName) {
+ auto* d = create<DepthTexture>(TextureDimension::kCube);
+ EXPECT_EQ(d->type_name(), "__depth_texture_cube");
+}
+
+TEST_F(AstDepthTextureTest, FriendlyName) {
+ auto* d = create<DepthTexture>(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 0000000..66a8fe0
--- /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<F32>(src);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/f32.h b/src/ast/f32.h
new file mode 100644
index 0000000..42e9bc7
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A float 32 type
+class F32 : public Castable<F32, Type> {
+ 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 0000000..2045d83
--- /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<F32>();
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_TRUE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstF32Test, TypeName) {
+ auto* f = create<F32>();
+ EXPECT_EQ(f->type_name(), "__f32");
+}
+
+TEST_F(AstF32Test, FriendlyName) {
+ auto* f = create<F32>();
+ 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 0000000..358e775
--- /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<I32>(src);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/i32.h b/src/ast/i32.h
new file mode 100644
index 0000000..182f102
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A signed int 32 type.
+class I32 : public Castable<I32, Type> {
+ 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 0000000..7a85707
--- /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<I32>();
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_TRUE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstI32Test, TypeName) {
+ auto* i = create<I32>();
+ EXPECT_EQ(i->type_name(), "__i32");
+}
+
+TEST_F(AstI32Test, FriendlyName) {
+ auto* i = create<I32>();
+ 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 e044cd6..1669270 100644
--- a/src/ast/intrinsic_texture_helper_test.cc
+++ b/src/ast/intrinsic_texture_helper_test.cc
@@ -63,7 +63,7 @@
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 e5c5628..b7a9a80 100644
--- a/src/ast/intrinsic_texture_helper_test.h
+++ b/src/ast/intrinsic_texture_helper_test.h
@@ -198,7 +198,7 @@
/// Constructor for textureLoad() with storage textures
TextureOverloadCase(ValidTextureOverload,
const char*,
- AccessControl,
+ AccessControl::Access,
sem::ImageFormat,
sem::TextureDimension,
TextureDataType,
@@ -236,7 +236,7 @@
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 0000000..da8e019
--- /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<Matrix>(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 0000000..1a419dd0
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A matrix type
+class Matrix : public Castable<Matrix, Type> {
+ 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 0000000..fc5e40b
--- /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<I32>();
+ auto* m = create<Matrix>(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<I32>();
+ Type* ty = create<Matrix>(i32, 2, 3);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_TRUE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstMatrixTest, TypeName) {
+ auto* i32 = create<I32>();
+ auto* m = create<Matrix>(i32, 2, 3);
+ EXPECT_EQ(m->type_name(), "__mat_2_3__i32");
+}
+
+TEST_F(AstMatrixTest, FriendlyName) {
+ auto* i32 = create<I32>();
+ auto* m = create<Matrix>(i32, 3, 2);
+ EXPECT_EQ(m->FriendlyName(Symbols()), "mat2x3<i32>");
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/module.cc b/src/ast/module.cc
index 31ac2f3..d6cc39a 100644
--- a/src/ast/module.cc
+++ b/src/ast/module.cc
@@ -89,7 +89,6 @@
str->impl()->to_str(sem, out, indent);
}
} else if (auto* str = ty->As<sem::StructType>()) {
- 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 0000000..5f907ab
--- /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<MultisampledTexture>(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 0000000..9fcc2a8
--- /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 <string>
+
+#include "src/ast/texture.h"
+
+namespace tint {
+namespace ast {
+
+/// A multisampled texture type.
+class MultisampledTexture : public Castable<MultisampledTexture, Texture> {
+ 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 0000000..277c25a
--- /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<F32>();
+ Type* ty = create<MultisampledTexture>(TextureDimension::kCube, f32);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_TRUE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstMultisampledTextureTest, IsTexture) {
+ auto* f32 = create<F32>();
+ Texture* ty = create<MultisampledTexture>(TextureDimension::kCube, f32);
+ EXPECT_FALSE(ty->Is<DepthTexture>());
+ EXPECT_TRUE(ty->Is<MultisampledTexture>());
+ EXPECT_FALSE(ty->Is<SampledTexture>());
+ EXPECT_FALSE(ty->Is<StorageTexture>());
+}
+
+TEST_F(AstMultisampledTextureTest, Dim) {
+ auto* f32 = create<F32>();
+ auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->dim(), TextureDimension::k3d);
+}
+
+TEST_F(AstMultisampledTextureTest, Type) {
+ auto* f32 = create<F32>();
+ auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->type(), f32);
+}
+
+TEST_F(AstMultisampledTextureTest, TypeName) {
+ auto* f32 = create<F32>();
+ auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->type_name(), "__multisampled_texture_3d__f32");
+}
+
+TEST_F(AstMultisampledTextureTest, FriendlyName) {
+ auto* f32 = create<F32>();
+ auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->FriendlyName(Symbols()), "texture_multisampled_3d<f32>");
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/pointer.cc b/src/ast/pointer.cc
new file mode 100644
index 0000000..3a968dc
--- /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<Pointer>(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 0000000..55882ed
--- /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 <string>
+
+#include "src/ast/storage_class.h"
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A pointer type.
+class Pointer : public Castable<Pointer, Type> {
+ 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 0000000..9e11d2e
--- /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<I32>();
+ auto* p = create<Pointer>(i32, ast::StorageClass::kStorage);
+ EXPECT_EQ(p->type(), i32);
+ EXPECT_EQ(p->storage_class(), ast::StorageClass::kStorage);
+}
+
+TEST_F(AstPointerTest, Is) {
+ auto* i32 = create<I32>();
+ Type* ty = create<Pointer>(i32, ast::StorageClass::kFunction);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_TRUE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstPointerTest, TypeName) {
+ auto* i32 = create<I32>();
+ auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup);
+ EXPECT_EQ(p->type_name(), "__ptr_workgroup__i32");
+}
+
+TEST_F(AstPointerTest, FriendlyNameWithStorageClass) {
+ auto* i32 = create<I32>();
+ auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup);
+ EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>");
+}
+
+TEST_F(AstPointerTest, FriendlyNameWithoutStorageClass) {
+ auto* i32 = create<I32>();
+ auto* p = create<Pointer>(i32, ast::StorageClass::kNone);
+ EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<i32>");
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/sampled_texture.cc b/src/ast/sampled_texture.cc
new file mode 100644
index 0000000..9e1ad0d
--- /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<SampledTexture>(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 0000000..f7d9af9
--- /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 <string>
+
+#include "src/ast/texture.h"
+
+namespace tint {
+namespace ast {
+
+/// A sampled texture type.
+class SampledTexture : public Castable<SampledTexture, Texture> {
+ 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 0000000..4cba040
--- /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<F32>();
+ Type* ty = create<SampledTexture>(TextureDimension::kCube, f32);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_TRUE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstSampledTextureTest, IsTexture) {
+ auto* f32 = create<F32>();
+ Texture* ty = create<SampledTexture>(TextureDimension::kCube, f32);
+ EXPECT_FALSE(ty->Is<DepthTexture>());
+ EXPECT_TRUE(ty->Is<SampledTexture>());
+ EXPECT_FALSE(ty->Is<StorageTexture>());
+}
+
+TEST_F(AstSampledTextureTest, Dim) {
+ auto* f32 = create<F32>();
+ auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->dim(), TextureDimension::k3d);
+}
+
+TEST_F(AstSampledTextureTest, Type) {
+ auto* f32 = create<F32>();
+ auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->type(), f32);
+}
+
+TEST_F(AstSampledTextureTest, TypeName) {
+ auto* f32 = create<F32>();
+ auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->type_name(), "__sampled_texture_3d__f32");
+}
+
+TEST_F(AstSampledTextureTest, FriendlyName) {
+ auto* f32 = create<F32>();
+ auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
+ EXPECT_EQ(s->FriendlyName(Symbols()), "texture_3d<f32>");
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/sampler.cc b/src/ast/sampler.cc
new file mode 100644
index 0000000..bcf95c8
--- /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<Sampler>(src, kind_);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/sampler.h b/src/ast/sampler.h
new file mode 100644
index 0000000..3800de9
--- /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 <string>
+
+#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<Sampler, Type> {
+ 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 0000000..9ddf1fe
--- /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<Sampler>(SamplerKind::kSampler);
+ EXPECT_EQ(s->kind(), SamplerKind::kSampler);
+}
+
+TEST_F(AstSamplerTest, Creation_ComparisonSampler) {
+ auto* s = create<Sampler>(SamplerKind::kComparisonSampler);
+ EXPECT_EQ(s->kind(), SamplerKind::kComparisonSampler);
+ EXPECT_TRUE(s->IsComparison());
+}
+
+TEST_F(AstSamplerTest, Is) {
+ Type* ty = create<Sampler>(SamplerKind::kSampler);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_TRUE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstSamplerTest, TypeName_Sampler) {
+ auto* s = create<Sampler>(SamplerKind::kSampler);
+ EXPECT_EQ(s->type_name(), "__sampler_sampler");
+}
+
+TEST_F(AstSamplerTest, TypeName_Comparison) {
+ auto* s = create<Sampler>(SamplerKind::kComparisonSampler);
+ EXPECT_EQ(s->type_name(), "__sampler_comparison");
+}
+
+TEST_F(AstSamplerTest, FriendlyNameSampler) {
+ auto* s = create<Sampler>(SamplerKind::kSampler);
+ EXPECT_EQ(s->FriendlyName(Symbols()), "sampler");
+}
+
+TEST_F(AstSamplerTest, FriendlyNameComparisonSampler) {
+ auto* s = create<Sampler>(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 0000000..f1f23d6
--- /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<StorageTexture>(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<U32>();
+ }
+
+ 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<I32>();
+ }
+
+ 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<F32>();
+ }
+
+ 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 0000000..bdf16b3
--- /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 <string>
+
+#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<StorageTexture, Texture> {
+ 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 0000000..0f29196
--- /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<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRgba32Float, subtype);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_TRUE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstStorageTextureTest, IsTexture) {
+ auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this);
+ Texture* ty = create<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRgba32Float, subtype);
+ EXPECT_FALSE(ty->Is<DepthTexture>());
+ EXPECT_FALSE(ty->Is<SampledTexture>());
+ EXPECT_TRUE(ty->Is<StorageTexture>());
+}
+
+TEST_F(AstStorageTextureTest, Dim) {
+ auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this);
+ auto* s = create<StorageTexture>(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<StorageTexture>(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<StorageTexture>(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<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRgba32Float, subtype);
+ EXPECT_EQ(s->FriendlyName(Symbols()),
+ "texture_storage_2d_array<rgba32float>");
+}
+
+TEST_F(AstStorageTextureTest, F32) {
+ auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Float, *this);
+ Type* s = create<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRgba32Float, subtype);
+
+ ASSERT_TRUE(s->Is<Texture>());
+ ASSERT_TRUE(s->Is<StorageTexture>());
+ EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<F32>());
+}
+
+TEST_F(AstStorageTextureTest, U32) {
+ auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRg32Uint, *this);
+ Type* s = create<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRg32Uint, subtype);
+
+ ASSERT_TRUE(s->Is<Texture>());
+ ASSERT_TRUE(s->Is<StorageTexture>());
+ EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<U32>());
+}
+
+TEST_F(AstStorageTextureTest, I32) {
+ auto* subtype = StorageTexture::SubtypeFor(ImageFormat::kRgba32Sint, *this);
+ Type* s = create<StorageTexture>(TextureDimension::k2dArray,
+ ImageFormat::kRgba32Sint, subtype);
+
+ ASSERT_TRUE(s->Is<Texture>());
+ ASSERT_TRUE(s->Is<StorageTexture>());
+ EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<I32>());
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index a3a396d..1ebf174 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -14,6 +14,8 @@
#include "src/ast/struct.h"
+#include <string>
+
#include "src/ast/struct_block_decoration.h"
#include "src/program_builder.h"
@@ -24,9 +26,11 @@
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 @@
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<Struct>(src, mem, decos);
+ return ctx->dst->create<Struct>(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 @@
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 b6a0314..770fb3e 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 <string>
#include <utility>
#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<Struct, Node> {
+class Struct : public Castable<Struct, Type> {
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 @@
~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 @@
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 b7f9b1f..6ac527c 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<Struct>(StructMemberList{Member("a", ty.i32())}, DecorationList{});
+TEST_F(AstStructTest, Creation) {
+ auto name = Sym("s");
+ auto* s = create<Struct>(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 @@
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<StructBlockDecoration>());
- auto* s = create<Struct>(StructMemberList{Member("a", ty.i32())}, decos);
+ auto* s =
+ create<Struct>(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<StructBlockDecoration>());
@@ -47,13 +64,13 @@
EXPECT_EQ(s->source().range.end.column, 0u);
}
-TEST_F(StructTest, CreationWithSourceAndDecorations) {
- DecorationList decos;
- decos.push_back(create<StructBlockDecoration>());
-
+TEST_F(AstStructTest, CreationWithSourceAndDecorations) {
+ auto name = Sym("s");
auto* s = create<Struct>(
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<StructBlockDecoration>()});
+ EXPECT_EQ(s->name(), name);
EXPECT_EQ(s->members().size(), 1u);
ASSERT_EQ(s->decorations().size(), 1u);
EXPECT_TRUE(s->decorations()[0]->Is<StructBlockDecoration>());
@@ -63,60 +80,95 @@
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<Struct>(StructMemberList{b.Member("a", b.ty.i32()), nullptr},
+ b.create<Struct>(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<Struct>(StructMemberList{b.Member("a", b.ty.i32())},
+ b.create<Struct>(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<Struct>(StructMemberList{b2.Member("a", b2.ty.i32())},
+ b1.create<Struct>(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<Struct>(StructMemberList{b1.Member("a", b1.ty.i32())},
+ b1.create<Struct>(b1.Sym("S"),
+ StructMemberList{b1.Member("a", b1.ty.i32())},
DecorationList{b2.create<StructBlockDecoration>()});
},
"internal compiler error");
}
-TEST_F(StructTest, ToStr) {
- DecorationList decos;
- decos.push_back(create<StructBlockDecoration>());
- auto* s = create<Struct>(StructMemberList{Member("a", ty.i32())}, decos);
+TEST_F(AstStructTest, ToStr) {
+ auto* s = create<Struct>(Sym("S"), StructMemberList{Member("a", ty.i32())},
+ DecorationList{create<StructBlockDecoration>()});
- EXPECT_EQ(str(s), R"(Struct{
+ EXPECT_EQ(str(s), R"(Struct S {
[[block]]
StructMember{a: __i32}
}
)");
}
+TEST_F(AstStructTest, Is) {
+ Type* ty = create<ast::Struct>(Sym("S"), ast::StructMemberList{},
+ ast::DecorationList{});
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_TRUE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstStructTest, TypeName) {
+ auto name = Sym("my_struct");
+ auto* s =
+ create<ast::Struct>(name, ast::StructMemberList{}, ast::DecorationList{});
+ EXPECT_EQ(s->type_name(), "__struct_$1");
+}
+
+TEST_F(AstStructTest, FriendlyName) {
+ auto name = Sym("my_struct");
+ auto* s =
+ create<ast::Struct>(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 0000000..28de192
--- /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 0000000..c8c871f
--- /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<Texture, Type> {
+ 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 0000000..10ff52b
--- /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 0000000..cd0bc0f
--- /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 <string>
+
+#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<Type, Node> {
+ 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 0000000..8a533c1
--- /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<U32>(src);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/u32.h b/src/ast/u32.h
new file mode 100644
index 0000000..22d3959
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A unsigned int 32 type.
+class U32 : public Castable<U32, Type> {
+ 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 0000000..94deea6
--- /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<U32>();
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_TRUE(ty->Is<U32>());
+ EXPECT_FALSE(ty->Is<Vector>());
+}
+
+TEST_F(AstU32Test, TypeName) {
+ auto* u = create<U32>();
+ EXPECT_EQ(u->type_name(), "__u32");
+}
+
+TEST_F(AstU32Test, FriendlyName) {
+ auto* u = create<U32>();
+ 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 0000000..60e52a3
--- /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<Vector>(src, ty, size_);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/vector.h b/src/ast/vector.h
new file mode 100644
index 0000000..13e7cad
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A vector type.
+class Vector : public Castable<Vector, Type> {
+ 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 0000000..940cdc3
--- /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<I32>();
+ auto* v = create<Vector>(i32, 2);
+ EXPECT_EQ(v->type(), i32);
+ EXPECT_EQ(v->size(), 2u);
+}
+
+TEST_F(AstVectorTest, Is) {
+ auto* i32 = create<I32>();
+ Type* ty = create<Vector>(i32, 4);
+ EXPECT_FALSE(ty->Is<AccessControl>());
+ EXPECT_FALSE(ty->Is<Alias>());
+ EXPECT_FALSE(ty->Is<Array>());
+ EXPECT_FALSE(ty->Is<Bool>());
+ EXPECT_FALSE(ty->Is<F32>());
+ EXPECT_FALSE(ty->Is<I32>());
+ EXPECT_FALSE(ty->Is<Matrix>());
+ EXPECT_FALSE(ty->Is<Pointer>());
+ EXPECT_FALSE(ty->Is<Sampler>());
+ EXPECT_FALSE(ty->Is<Struct>());
+ EXPECT_FALSE(ty->Is<Texture>());
+ EXPECT_FALSE(ty->Is<U32>());
+ EXPECT_TRUE(ty->Is<Vector>());
+}
+
+TEST_F(AstVectorTest, TypeName) {
+ auto* i32 = create<I32>();
+ auto* v = create<Vector>(i32, 3);
+ EXPECT_EQ(v->type_name(), "__vec_3__i32");
+}
+
+TEST_F(AstVectorTest, FriendlyName) {
+ auto* v = ty.vec3<f32>();
+ EXPECT_EQ(v->FriendlyName(Symbols()), "vec3<f32>");
+}
+
+} // namespace
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/void.cc b/src/ast/void.cc
new file mode 100644
index 0000000..5591ceb
--- /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<Void>(src);
+}
+
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/void.h b/src/ast/void.h
new file mode 100644
index 0000000..3ed79b0
--- /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 <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A void type
+class Void : public Castable<Void, Type> {
+ 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 f02f1f3..68f0683 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -225,8 +225,9 @@
decos.push_back(create<ast::StructBlockDecoration>());
}
- auto* str = create<ast::Struct>(members, decos);
- auto* str_ty = ty.struct_(name, str);
+ auto sym = Sym(name);
+ auto* str = create<ast::Struct>(sym, members, decos);
+ auto* str_ty = ty.struct_(sym, str);
AST().AddConstructedType(str_ty);
return str_ty;
}
@@ -1824,6 +1825,7 @@
TEST_F(InspectorGetUniformBufferResourceBindingsTest, MissingBlockDeco) {
ast::DecorationList decos;
auto* str = create<ast::Struct>(
+ 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 db7dc54..40d2ef1 100644
--- a/src/intrinsic_table.cc
+++ b/src/intrinsic_table.cc
@@ -603,7 +603,7 @@
/// 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 @@
}
private:
- ast::AccessControl const access_control_;
+ ast::AccessControl::Access const access_control_;
Builder* const type_;
};
@@ -765,7 +765,8 @@
}
/// @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<AccessControlBuilder>(access_control,
type);
}
diff --git a/src/program_builder.h b/src/program_builder.h
index e5dbe14..3e518fc 100644
--- a/src/program_builder.h
+++ b/src/program_builder.h
@@ -535,7 +535,7 @@
/// @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<sem::AccessControl>(access, type);
}
@@ -1185,9 +1185,10 @@
NAME&& name,
ast::StructMemberList members,
ast::DecorationList decorations = {}) {
- auto* impl =
- create<ast::Struct>(source, std::move(members), std::move(decorations));
- auto* type = ty.struct_(Sym(std::forward<NAME>(name)), impl);
+ auto sym = Sym(std::forward<NAME>(name));
+ auto* impl = create<ast::Struct>(source, sym, std::move(members),
+ std::move(decorations));
+ auto* type = ty.struct_(sym, impl);
AST().AddConstructedType(type);
return type;
}
@@ -1202,9 +1203,10 @@
sem::StructType* Structure(NAME&& name,
ast::StructMemberList members,
ast::DecorationList decorations = {}) {
+ auto sym = Sym(std::forward<NAME>(name));
auto* impl =
- create<ast::Struct>(std::move(members), std::move(decorations));
- auto* type = ty.struct_(Sym(std::forward<NAME>(name)), impl);
+ create<ast::Struct>(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 1f9a48e..00e94b6 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -1338,7 +1338,8 @@
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 6e0c699..2870f5a 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -798,7 +798,7 @@
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 87315ca..e22c749 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -551,7 +551,7 @@
if (where == inst_source_.end()) {
return {};
}
- return Source{where->second };
+ return Source{where->second};
}
bool ParserImpl::ParseInternalModuleExceptFunctions() {
@@ -940,15 +940,16 @@
return nullptr;
}
- // Now make the struct.
- auto* ast_struct = create<ast::Struct>(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<sem::StructType>(
- builder_.Symbols().Register(name), ast_struct);
+
+ // Now make the struct.
+ auto sym = builder_.Symbols().Register(name);
+ auto* ast_struct = create<ast::Struct>(Source{}, sym, std::move(ast_members),
+ std::move(ast_struct_decorations));
+
+ auto* result = builder_.create<sem::StructType>(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 5957329..5915beb 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 @@
EXPECT_TRUE(type->Is<sem::StructType>());
Program program = p->program();
- EXPECT_THAT(program.str(type->As<sem::StructType>()->impl()), Eq(R"(Struct{
+ EXPECT_THAT(program.str(type->As<sem::StructType>()->impl()), Eq(R"(Struct S {
StructMember{field0: __u32}
StructMember{field1: __f32}
}
@@ -574,7 +574,7 @@
EXPECT_TRUE(type->Is<sem::StructType>());
Program program = p->program();
- EXPECT_THAT(program.str(type->As<sem::StructType>()->impl()), Eq(R"(Struct{
+ EXPECT_THAT(program.str(type->As<sem::StructType>()->impl()), Eq(R"(Struct S {
[[block]]
StructMember{field0: __u32}
}
@@ -599,7 +599,7 @@
EXPECT_TRUE(type->Is<sem::StructType>());
Program program = p->program();
- EXPECT_THAT(program.str(type->As<sem::StructType>()->impl()), Eq(R"(Struct{
+ EXPECT_THAT(program.str(type->As<sem::StructType>()->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 220261e..b52daa2 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 9f029d8..2366939 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 @@
%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 @@
%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 @@
%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 d230a95..6db1b7e 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -836,7 +836,7 @@
return TypedIdentifier{ty, ident.value, ident.source};
}
-Expect<ast::AccessControl> ParserImpl::expect_access_type() {
+Expect<ast::AccessControl::Access> ParserImpl::expect_access_type() {
auto ident = expect_ident("access_type");
if (ident.errored)
return Failure::kErrored;
@@ -1134,9 +1134,10 @@
if (body.errored)
return Failure::kErrored;
+ auto sym = builder_.Symbols().Register(name.value);
return create<sem::StructType>(
- builder_.Symbols().Register(name.value),
- create<ast::Struct>(source, std::move(body.value), std::move(decos)));
+ sym, create<ast::Struct>(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 b15fd16..a7ae443 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -437,7 +437,7 @@
/// Parses an access type identifier, erroring if the next token does not
/// match a valid access type name.
/// @returns the parsed access control.
- Expect<ast::AccessControl> expect_access_type();
+ Expect<ast::AccessControl::Access> 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 3270881..6719ade 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 @@
ast::DecorationList decos;
decos.push_back(block_deco);
- auto* str = create<ast::Struct>(members, decos);
+ auto* str = create<ast::Struct>(Sym("S"), members, decos);
auto* s = ty.struct_("S", str);
p->register_constructed("S", s);
@@ -140,7 +140,7 @@
ast::DecorationList decos;
decos.push_back(block_deco);
- auto* str = create<ast::Struct>(members, decos);
+ auto* str = create<ast::Struct>(Sym("S"), members, decos);
auto* s = ty.struct_("S", str);
p->register_constructed("S", s);
@@ -165,7 +165,7 @@
ast::DecorationList decos;
decos.push_back(block_deco);
- auto* str = create<ast::Struct>(members, decos);
+ auto* str = create<ast::Struct>(Sym("S"), members, decos);
auto* s = ty.struct_("S", str);
p->register_constructed("S", s);
@@ -187,7 +187,7 @@
ast::DecorationList decos;
decos.push_back(block_deco);
- auto* str = create<ast::Struct>(members, decos);
+ auto* str = create<ast::Struct>(Sym("S"), members, decos);
auto* s = ty.struct_("S", str);
p->register_constructed("S", s);
@@ -225,7 +225,7 @@
ast::DecorationList decos;
decos.push_back(block_deco);
- auto* str = create<ast::Struct>(members, decos);
+ auto* str = create<ast::Struct>(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 cb4f29f..b60a95d 100644
--- a/src/resolver/decoration_validation_test.cc
+++ b/src/resolver/decoration_validation_test.cc
@@ -131,7 +131,8 @@
ast::DecorationList{createDecoration(
Source{{12, 34}}, *this, params.kind)}))};
auto* s = create<ast::Struct>(
- members, ast::DecorationList{create<ast::StructBlockDecoration>()});
+ Sym("mystruct"), members,
+ ast::DecorationList{create<ast::StructBlockDecoration>()});
auto* s_ty = ty.struct_("mystruct", s);
AST().AddConstructedType(s_ty);
@@ -166,7 +167,7 @@
TEST_P(StructDecorationTest, IsValid) {
auto& params = GetParam();
- auto* s = create<ast::Struct>(ast::StructMemberList{},
+ auto* s = create<ast::Struct>(Sym("mystruct"), ast::StructMemberList{},
ast::DecorationList{createDecoration(
Source{{12, 34}}, *this, params.kind)});
auto* s_ty = ty.struct_("mystruct", s);
@@ -207,7 +208,8 @@
Member("a", ty.i32(),
ast::DecorationList{
createDecoration(Source{{12, 34}}, *this, params.kind)})};
- auto* s = create<ast::Struct>(members, ast::DecorationList{});
+ auto* s =
+ create<ast::Struct>(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 6ea8536..23bede2 100644
--- a/src/resolver/resolver_test.cc
+++ b/src/resolver/resolver_test.cc
@@ -889,6 +889,7 @@
TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
auto* strct = create<ast::Struct>(
+ 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_Alias) {
auto* strct = create<ast::Struct>(
+ Sym("alias"),
ast::StructMemberList{Member("first_member", ty.i32()),
Member("second_member", ty.f32())},
ast::DecorationList{});
@@ -999,14 +1001,15 @@
// }
//
- auto* strctB =
- create<ast::Struct>(ast::StructMemberList{Member("foo", ty.vec4<f32>())},
- ast::DecorationList{});
+ auto* strctB = create<ast::Struct>(
+ Sym("B"), ast::StructMemberList{Member("foo", ty.vec4<f32>())},
+ ast::DecorationList{});
auto* stB = ty.struct_("B", strctB);
sem::Vector vecB(stB, 3);
- auto* strctA = create<ast::Struct>(
- ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{});
+ auto* strctA =
+ create<ast::Struct>(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_MemberAccessor_InBinaryOp) {
auto* strct = create<ast::Struct>(
+ 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 138efe9..49aeb13 100644
--- a/src/resolver/type_validation_test.cc
+++ b/src/resolver/type_validation_test.cc
@@ -315,7 +315,8 @@
ast::DecorationList decos;
decos.push_back(create<ast::StructBlockDecoration>());
auto* st =
- create<ast::Struct>(ast::StructMemberList{Member("vf", ty.f32()),
+ create<ast::Struct>(Sym("Foo"),
+ ast::StructMemberList{Member("vf", ty.f32()),
Member("rt", ty.array<f32>())},
decos);
@@ -335,6 +336,7 @@
ast::DecorationList decos;
auto* st = create<ast::Struct>(
+ Sym("Foo"),
ast::StructMemberList{Member("vf", ty.f32()),
Member(Source{{12, 34}}, "rt", ty.array<f32>())},
decos);
@@ -362,7 +364,7 @@
auto* rt = Member(Source{{12, 34}}, "rt", ty.array<f32>());
auto* st = create<ast::Struct>(
- 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 @@
ast::DecorationList decos;
decos.push_back(create<ast::StructBlockDecoration>());
auto* st = create<ast::Struct>(
+ Sym("s"),
ast::StructMemberList{Member(Source{{12, 34}}, "b", alias),
Member("a", ty.u32())},
decos);
@@ -467,6 +470,7 @@
ast::DecorationList decos;
decos.push_back(create<ast::StructBlockDecoration>());
auto* st = create<ast::Struct>(
+ 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 09e9af2..6c3101f 100644
--- a/src/sem/access_control_type.cc
+++ b/src/sem/access_control_type.cc
@@ -21,7 +21,7 @@
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<AccessControl>());
diff --git a/src/sem/access_control_type.h b/src/sem/access_control_type.h
index 7f6ac37..5772970 100644
--- a/src/sem/access_control_type.h
+++ b/src/sem/access_control_type.h
@@ -29,7 +29,7 @@
/// 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 @@
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 @@
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 8179d9f..e91cd00 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<ExternalTexture, Texture> {
public:
/// Constructor
@@ -46,4 +48,5 @@
} // 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 a667cfa..0571c88 100644
--- a/src/sem/struct_type_test.cc
+++ b/src/sem/struct_type_test.cc
@@ -23,17 +23,19 @@
using StructTypeTest = TestHelper;
TEST_F(StructTypeTest, Creation) {
+ auto name = Sym("S");
auto* impl =
- create<ast::Struct>(ast::StructMemberList{}, ast::DecorationList{});
+ create<ast::Struct>(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::Struct>(ast::StructMemberList{}, ast::DecorationList{});
- auto* s = ty.struct_("S", impl);
+ create<ast::Struct>(name, ast::StructMemberList{}, ast::DecorationList{});
+ auto* s = ty.struct_(name, impl);
sem::Type* ty = s;
EXPECT_FALSE(ty->Is<AccessControl>());
EXPECT_FALSE(ty->Is<Alias>());
@@ -51,16 +53,18 @@
}
TEST_F(StructTypeTest, TypeName) {
+ auto name = Sym("my_struct");
auto* impl =
- create<ast::Struct>(ast::StructMemberList{}, ast::DecorationList{});
- auto* s = ty.struct_("my_struct", impl);
+ create<ast::Struct>(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::Struct>(ast::StructMemberList{}, ast::DecorationList{});
- auto* s = ty.struct_("my_struct", impl);
+ create<ast::Struct>(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 2dc14a3..1a19e78 100644
--- a/src/transform/binding_remapper.cc
+++ b/src/transform/binding_remapper.cc
@@ -63,7 +63,7 @@
// 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<sem::AccessControl>()) {
diff --git a/src/transform/binding_remapper.h b/src/transform/binding_remapper.h
index b80d823..4b6ef83 100644
--- a/src/transform/binding_remapper.h
+++ b/src/transform/binding_remapper.h
@@ -32,7 +32,8 @@
using BindingPoints = std::unordered_map<BindingPoint, BindingPoint>;
/// AccessControls is a map of old binding point to new access control
- using AccessControls = std::unordered_map<BindingPoint, ast::AccessControl>;
+ using AccessControls =
+ std::unordered_map<BindingPoint, ast::AccessControl::Access>;
/// 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 90d72b1..55b86d1 100644
--- a/src/transform/canonicalize_entry_point_io.cc
+++ b/src/transform/canonicalize_entry_point_io.cc
@@ -81,10 +81,11 @@
}
// Redeclare the struct.
+ auto new_struct_name = ctx.Clone(struct_ty->symbol());
auto* new_struct = ctx.dst->create<sem::StructType>(
- ctx.Clone(struct_ty->symbol()),
- ctx.dst->create<ast::Struct>(
- new_struct_members, ctx.Clone(struct_ty->impl()->decorations())));
+ new_struct_name, ctx.dst->create<ast::Struct>(
+ new_struct_name, new_struct_members,
+ ctx.Clone(struct_ty->impl()->decorations())));
ctx.Replace(struct_ty, new_struct);
}
}
@@ -174,9 +175,10 @@
StructMemberComparator);
// Create the new struct type.
+ auto in_struct_name = ctx.dst->Symbols().New();
auto* in_struct = ctx.dst->create<sem::StructType>(
- ctx.dst->Symbols().New(),
- ctx.dst->create<ast::Struct>(new_struct_members,
+ in_struct_name,
+ ctx.dst->create<ast::Struct>(in_struct_name, new_struct_members,
ast::DecorationList{}));
ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func, in_struct);
@@ -220,9 +222,10 @@
StructMemberComparator);
// Create the new struct type.
+ auto out_struct_name = ctx.dst->Symbols().New();
auto* out_struct = ctx.dst->create<sem::StructType>(
- ctx.dst->Symbols().New(),
- ctx.dst->create<ast::Struct>(new_struct_members,
+ out_struct_name,
+ ctx.dst->create<ast::Struct>(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 e16a22a..09d7324 100644
--- a/src/transform/spirv.cc
+++ b/src/transform/spirv.cc
@@ -126,10 +126,11 @@
}
// Redeclare the struct.
+ auto new_struct_name = ctx.Clone(struct_ty->symbol());
auto* new_struct = ctx.dst->create<sem::StructType>(
- ctx.Clone(struct_ty->symbol()),
- ctx.dst->create<ast::Struct>(
- new_struct_members, ctx.Clone(struct_ty->impl()->decorations())));
+ new_struct_name, ctx.dst->create<ast::Struct>(
+ 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 de53041..610f9b5 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -3145,7 +3145,7 @@
}
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 5f44e0f..bea880d 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -450,7 +450,7 @@
/// @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 167fef7..0ac4460 100644
--- a/src/writer/wgsl/generator_impl_type_test.cc
+++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -436,7 +436,7 @@
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 ba2a815..2b19a60 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -138,14 +138,18 @@
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 @@
"../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 @@
"../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 @@
"../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 @@
"../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 @@
"../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",