ast: Replace NamedType with TypeDecl

TypeDecls (alias, structure) are not a types - they declare types.
ast::TypeName is what's used for a ast::Type.

Previously we were trying to automatically convert these to TypeNames in the builder, but having these inherit from ast::Type was extremely error prone.

reader/spirv was actually constructing ast::Structs and using them as types, which is invalid.

Change-Id: I05773ad6d488626606019015b84217a5a55a8e8a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53802
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Ben Clayton 2021-06-09 14:32:14 +00:00
parent 6e7d24d36a
commit 8758f10a20
81 changed files with 539 additions and 522 deletions

View File

@ -382,8 +382,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/module.h", "ast/module.h",
"ast/multisampled_texture.cc", "ast/multisampled_texture.cc",
"ast/multisampled_texture.h", "ast/multisampled_texture.h",
"ast/named_type.cc",
"ast/named_type.h",
"ast/node.cc", "ast/node.cc",
"ast/node.h", "ast/node.h",
"ast/override_decoration.cc", "ast/override_decoration.cc",
@ -431,6 +429,8 @@ libtint_source_set("libtint_core_all_src") {
"ast/type.h", "ast/type.h",
"ast/type_constructor_expression.cc", "ast/type_constructor_expression.cc",
"ast/type_constructor_expression.h", "ast/type_constructor_expression.h",
"ast/type_decl.cc",
"ast/type_decl.h",
"ast/type_name.cc", "ast/type_name.cc",
"ast/type_name.h", "ast/type_name.h",
"ast/u32.cc", "ast/u32.cc",

View File

@ -126,8 +126,6 @@ set(TINT_LIB_SRCS
ast/module.h ast/module.h
ast/multisampled_texture.cc ast/multisampled_texture.cc
ast/multisampled_texture.h ast/multisampled_texture.h
ast/named_type.cc
ast/named_type.h
ast/node.cc ast/node.cc
ast/node.h ast/node.h
ast/override_decoration.cc ast/override_decoration.cc
@ -178,6 +176,8 @@ set(TINT_LIB_SRCS
ast/type_name.h ast/type_name.h
ast/ast_type.cc # TODO(bclayton) - rename to type.cc ast/ast_type.cc # TODO(bclayton) - rename to type.cc
ast/type.h ast/type.h
ast/type_decl.cc
ast/type_decl.h
ast/type_name.cc ast/type_name.cc
ast/type_name.h ast/type_name.h
ast/u32.cc ast/u32.cc

View File

@ -17,13 +17,13 @@
#include <string> #include <string>
#include "src/ast/named_type.h" #include "src/ast/type_decl.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
/// A type alias type. Holds a name and pointer to another type. /// A type alias type. Holds a name and pointer to another type.
class Alias : public Castable<Alias, NamedType> { class Alias : public Castable<Alias, TypeDecl> {
public: public:
/// Constructor /// Constructor
/// @param program_id the identifier of the program that owns this node /// @param program_id the identifier of the program that owns this node

View File

@ -46,7 +46,7 @@ TEST_F(AstAliasTest, Create) {
TEST_F(AstAliasTest, TypeName_LinearTime) { TEST_F(AstAliasTest, TypeName_LinearTime) {
Type* type = ty.i32(); Type* type = ty.i32();
for (int i = 0; i < 1024; i++) { for (int i = 0; i < 1024; i++) {
type = Alias(Symbols().New(), type); type = ty.Of(Alias(Symbols().New(), type));
} }
for (int i = 0; i < 16384; i++) { for (int i = 0; i < 16384; i++) {
type->type_name(); type->type_name();
@ -58,24 +58,6 @@ TEST_F(AstAliasTest, TypeName) {
EXPECT_EQ(at->type_name(), "__alias_$1__i32"); EXPECT_EQ(at->type_name(), "__alias_$1__i32");
} }
TEST_F(AstAliasTest, FriendlyName) {
auto* at = Alias("Particle", create<I32>());
EXPECT_EQ(at->FriendlyName(Symbols()), "Particle");
}
TEST_F(AstAliasTest, UnwrapAll_TwiceAliasPointerTwiceAlias) {
auto* u32 = create<U32>();
auto* a = create<ast::Alias>(Sym("a_type"), u32);
auto* aa = create<ast::Alias>(Sym("aa_type"), a);
auto* paa = create<Pointer>(aa, StorageClass::kUniform, Access::kUndefined);
auto* apaa = create<ast::Alias>(Sym("paa_type"), paa);
auto* aapaa = create<ast::Alias>(Sym("aapaa_type"), apaa);
EXPECT_EQ(aapaa->symbol(), Symbol(4, ID()));
EXPECT_EQ(aapaa->type(), apaa);
EXPECT_EQ(aapaa->UnwrapAll(), u32);
}
} // namespace } // namespace
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -40,9 +40,7 @@ Type::~Type() = default;
Type* Type::UnwrapAll() { Type* Type::UnwrapAll() {
auto* type = this; auto* type = this;
while (true) { while (true) {
if (auto* alias = type->As<Alias>()) { if (auto* ptr = type->As<Pointer>()) {
type = alias->type();
} else if (auto* ptr = type->As<Pointer>()) {
type = ptr->type(); type = ptr->type();
} else { } else {
break; break;

View File

@ -16,7 +16,7 @@
#include <utility> #include <utility>
#include "src/ast/named_type.h" #include "src/ast/type_decl.h"
#include "src/program_builder.h" #include "src/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::Module); TINT_INSTANTIATE_TYPEINFO(tint::ast::Module);
@ -36,7 +36,7 @@ Module::Module(ProgramID program_id,
continue; continue;
} }
if (auto* ty = decl->As<ast::NamedType>()) { if (auto* ty = decl->As<ast::TypeDecl>()) {
constructed_types_.push_back(ty); constructed_types_.push_back(ty);
} else if (auto* func = decl->As<Function>()) { } else if (auto* func = decl->As<Function>()) {
functions_.push_back(func); functions_.push_back(func);
@ -51,7 +51,7 @@ Module::Module(ProgramID program_id,
Module::~Module() = default; Module::~Module() = default;
const ast::NamedType* Module::LookupType(Symbol name) const { const ast::TypeDecl* Module::LookupType(Symbol name) const {
for (auto* ty : ConstructedTypes()) { for (auto* ty : ConstructedTypes()) {
if (ty->name() == name) { if (ty->name() == name) {
return ty; return ty;
@ -67,7 +67,7 @@ void Module::AddGlobalVariable(ast::Variable* var) {
global_declarations_.push_back(var); global_declarations_.push_back(var);
} }
void Module::AddConstructedType(ast::NamedType* type) { void Module::AddConstructedType(ast::TypeDecl* type) {
TINT_ASSERT(type); TINT_ASSERT(type);
constructed_types_.push_back(type); constructed_types_.push_back(type);
global_declarations_.push_back(type); global_declarations_.push_back(type);
@ -92,7 +92,7 @@ void Module::Copy(CloneContext* ctx, const Module* src) {
TINT_ICE(ctx->dst->Diagnostics()) << "src global declaration was nullptr"; TINT_ICE(ctx->dst->Diagnostics()) << "src global declaration was nullptr";
continue; continue;
} }
if (auto* ty = decl->As<ast::NamedType>()) { if (auto* ty = decl->As<ast::TypeDecl>()) {
AddConstructedType(ty); AddConstructedType(ty);
} else if (auto* func = decl->As<Function>()) { } else if (auto* func = decl->As<Function>()) {
AddFunction(func); AddFunction(func);
@ -115,9 +115,6 @@ void Module::to_str(const sem::Info& sem,
if (auto* alias = ty->As<ast::Alias>()) { if (auto* alias = ty->As<ast::Alias>()) {
out << alias->symbol().to_str() << " -> " << alias->type()->type_name() out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
<< std::endl; << std::endl;
if (auto* str = alias->type()->As<ast::Struct>()) {
str->to_str(sem, out, indent);
}
} else if (auto* str = ty->As<ast::Struct>()) { } else if (auto* str = ty->As<ast::Struct>()) {
str->to_str(sem, out, indent); str->to_str(sem, out, indent);
} }

View File

@ -24,7 +24,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
class NamedType; class TypeDecl;
/// Module holds the top-level AST types, functions and global variables used by /// Module holds the top-level AST types, functions and global variables used by
/// a Program. /// a Program.
@ -73,16 +73,16 @@ class Module : public Castable<Module, Node> {
/// @returns the global variables for the translation unit /// @returns the global variables for the translation unit
VariableList& GlobalVariables() { return global_variables_; } VariableList& GlobalVariables() { return global_variables_; }
/// Adds a constructed type to the Builder. /// Adds a type declaration to the Builder.
/// @param type the constructed type to add /// @param decl the constructed type declaration to add
void AddConstructedType(ast::NamedType* type); void AddConstructedType(ast::TypeDecl* decl);
/// @returns the NamedType registered as a ConstructedType() /// @returns the TypeDecl registered as a ConstructedType()
/// @param name the name of the type to search for /// @param name the name of the type to search for
const ast::NamedType* LookupType(Symbol name) const; const ast::TypeDecl* LookupType(Symbol name) const;
/// @returns the constructed types in the translation unit /// @returns the constructed types in the translation unit
const std::vector<ast::NamedType*>& ConstructedTypes() const { const std::vector<ast::TypeDecl*>& ConstructedTypes() const {
return constructed_types_; return constructed_types_;
} }
@ -118,7 +118,7 @@ class Module : public Castable<Module, Node> {
private: private:
std::vector<ast::Node*> global_declarations_; std::vector<ast::Node*> global_declarations_;
std::vector<ast::NamedType*> constructed_types_; std::vector<ast::TypeDecl*> constructed_types_;
FunctionList functions_; FunctionList functions_;
VariableList global_variables_; VariableList global_variables_;
}; };

View File

@ -19,14 +19,14 @@
#include <utility> #include <utility>
#include "src/ast/decoration.h" #include "src/ast/decoration.h"
#include "src/ast/named_type.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/type_decl.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
/// A struct statement. /// A struct statement.
class Struct : public Castable<Struct, NamedType> { class Struct : public Castable<Struct, TypeDecl> {
public: public:
/// Create a new struct statement /// Create a new struct statement
/// @param program_id the identifier of the program that owns this node /// @param program_id the identifier of the program that owns this node

View File

@ -144,13 +144,6 @@ TEST_F(AstStructTest, TypeName) {
EXPECT_EQ(s->type_name(), "__struct_$1"); 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
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -12,26 +12,29 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/named_type.h" #include "src/ast/type_decl.h"
#include "src/program_builder.h" #include "src/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::NamedType); TINT_INSTANTIATE_TYPEINFO(tint::ast::TypeDecl);
namespace tint { namespace tint {
namespace ast { namespace ast {
NamedType::NamedType(ProgramID program_id, const Source& source, Symbol name) TypeDecl::TypeDecl(ProgramID program_id, const Source& source, Symbol name)
: Base(program_id, source), name_(name) { : Base(program_id, source), name_(name) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(name, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(name, program_id);
} }
NamedType::NamedType(NamedType&&) = default; TypeDecl::TypeDecl(TypeDecl&&) = default;
NamedType::~NamedType() = default; TypeDecl::~TypeDecl() = default;
std::string NamedType::FriendlyName(const SymbolTable& symbols) const { void TypeDecl::to_str(const sem::Info&,
return symbols.NameFor(name()); std::ostream& out,
size_t indent) const {
make_indent(out, indent);
out << type_name();
} }
} // namespace ast } // namespace ast

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef SRC_AST_NAMED_TYPE_H_ #ifndef SRC_AST_TYPE_DECL_H_
#define SRC_AST_NAMED_TYPE_H_ #define SRC_AST_TYPE_DECL_H_
#include <string> #include <string>
@ -22,30 +22,36 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
/// The base class for user declared, named types. /// The base class for type declarations.
class NamedType : public Castable<NamedType, Type> { class TypeDecl : public Castable<TypeDecl, Node> {
public: public:
/// Create a new struct statement /// Create a new struct statement
/// @param program_id the identifier of the program that owns this node /// @param program_id the identifier of the program that owns this node
/// @param source The input source for the import statement /// @param source The input source for the import statement
/// @param name The name of the structure /// @param name The name of the structure
NamedType(ProgramID program_id, const Source& source, Symbol name); TypeDecl(ProgramID program_id, const Source& source, Symbol name);
/// Move constructor /// Move constructor
NamedType(NamedType&&); TypeDecl(TypeDecl&&);
~NamedType() override; ~TypeDecl() override;
/// @returns the name of the structure /// @returns the name of the type declaration
Symbol name() const { return name_; } Symbol name() const { return name_; }
/// @param symbols the program's symbol table /// Writes a representation of the node to the output stream
/// @returns the name for this type that closely resembles how it would be /// @param sem the semantic info for the program
/// declared in WGSL. /// @param out the stream to write to
std::string FriendlyName(const SymbolTable& symbols) const override; /// @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;
/// @returns the name for this type. The type name is unique over all types.
virtual std::string type_name() const = 0;
private: private:
NamedType(const NamedType&) = delete; TypeDecl(const TypeDecl&) = delete;
NamedType& operator=(const NamedType&) = delete; TypeDecl& operator=(const TypeDecl&) = delete;
Symbol const name_; Symbol const name_;
}; };
@ -53,4 +59,4 @@ class NamedType : public Castable<NamedType, Type> {
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint
#endif // SRC_AST_NAMED_TYPE_H_ #endif // SRC_AST_TYPE_DECL_H_

View File

@ -1006,8 +1006,8 @@ TEST_F(InspectorGetEntryPointTest, BuiltInsNotStageVariables) {
TEST_F(InspectorGetEntryPointTest, InOutStruct) { TEST_F(InspectorGetEntryPointTest, InOutStruct) {
auto* interface = MakeInOutStruct("interface", {{"a", 0u}, {"b", 1u}}); auto* interface = MakeInOutStruct("interface", {{"a", 0u}, {"b", 1u}});
Func("foo", {Param("param", interface)}, interface, {Return("param")}, Func("foo", {Param("param", ty.Of(interface))}, ty.Of(interface),
{Stage(ast::PipelineStage::kFragment)}); {Return("param")}, {Stage(ast::PipelineStage::kFragment)});
Inspector& inspector = Build(); Inspector& inspector = Build();
auto result = inspector.GetEntryPoints(); auto result = inspector.GetEntryPoints();
@ -1038,9 +1038,9 @@ TEST_F(InspectorGetEntryPointTest, InOutStruct) {
TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutSharedStruct) { TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutSharedStruct) {
auto* interface = MakeInOutStruct("interface", {{"a", 0u}, {"b", 1u}}); auto* interface = MakeInOutStruct("interface", {{"a", 0u}, {"b", 1u}});
Func("foo", {}, interface, {Return(Construct(interface))}, Func("foo", {}, ty.Of(interface), {Return(Construct(ty.Of(interface)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
Func("bar", {Param("param", interface)}, ty.void_(), {}, Func("bar", {Param("param", ty.Of(interface))}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
Inspector& inspector = Build(); Inspector& inspector = Build();
@ -1078,10 +1078,11 @@ TEST_F(InspectorGetEntryPointTest, MixInOutVariablesAndStruct) {
auto* struct_a = MakeInOutStruct("struct_a", {{"a", 0u}, {"b", 1u}}); auto* struct_a = MakeInOutStruct("struct_a", {{"a", 0u}, {"b", 1u}});
auto* struct_b = MakeInOutStruct("struct_b", {{"a", 2u}}); auto* struct_b = MakeInOutStruct("struct_b", {{"a", 2u}});
Func("foo", Func("foo",
{Param("param_a", struct_a), Param("param_b", struct_b), {Param("param_a", ty.Of(struct_a)), Param("param_b", ty.Of(struct_b)),
Param("param_c", ty.f32(), {Location(3u)}), Param("param_c", ty.f32(), {Location(3u)}),
Param("param_d", ty.f32(), {Location(4u)})}, Param("param_d", ty.f32(), {Location(4u)})},
struct_a, {Return("param_a")}, {Stage(ast::PipelineStage::kFragment)}); ty.Of(struct_a), {Return("param_a")},
{Stage(ast::PipelineStage::kFragment)});
Inspector& inspector = Build(); Inspector& inspector = Build();
auto result = inspector.GetEntryPoints(); auto result = inspector.GetEntryPoints();
@ -1660,7 +1661,7 @@ TEST_F(InspectorGetResourceBindingsTest, Empty) {
TEST_F(InspectorGetResourceBindingsTest, Simple) { TEST_F(InspectorGetResourceBindingsTest, Simple) {
ast::Struct* ub_struct_type = MakeUniformBufferType("ub_type", {ty.i32()}); ast::Struct* ub_struct_type = MakeUniformBufferType("ub_type", {ty.i32()});
AddUniformBuffer("ub_var", ub_struct_type, 0, 0); AddUniformBuffer("ub_var", ty.Of(ub_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction("ub_func", "ub_var", {{0, ty.i32()}}); MakeStructVariableReferenceBodyFunction("ub_func", "ub_var", {{0, ty.i32()}});
auto sb = MakeStorageBufferTypes("sb_type", {ty.i32()}); auto sb = MakeStorageBufferTypes("sb_type", {ty.i32()});
@ -1768,7 +1769,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, MissingEntryPoint) {
TEST_F(InspectorGetUniformBufferResourceBindingsTest, NonEntryPointFunc) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, NonEntryPointFunc) {
ast::Struct* foo_struct_type = MakeUniformBufferType("foo_type", {ty.i32()}); ast::Struct* foo_struct_type = MakeUniformBufferType("foo_type", {ty.i32()});
AddUniformBuffer("foo_ub", foo_struct_type, 0, 0); AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}}); MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}});
@ -1786,7 +1787,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, NonEntryPointFunc) {
TEST_F(InspectorGetUniformBufferResourceBindingsTest, Simple) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, Simple) {
ast::Struct* foo_struct_type = MakeUniformBufferType("foo_type", {ty.i32()}); ast::Struct* foo_struct_type = MakeUniformBufferType("foo_type", {ty.i32()});
AddUniformBuffer("foo_ub", foo_struct_type, 0, 0); AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}}); MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}});
@ -1812,7 +1813,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, Simple) {
TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleMembers) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleMembers) {
ast::Struct* foo_struct_type = ast::Struct* foo_struct_type =
MakeUniformBufferType("foo_type", {ty.i32(), ty.u32(), ty.f32()}); MakeUniformBufferType("foo_type", {ty.i32(), ty.u32(), ty.f32()});
AddUniformBuffer("foo_ub", foo_struct_type, 0, 0); AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction( MakeStructVariableReferenceBodyFunction(
"ub_func", "foo_ub", {{0, ty.i32()}, {1, ty.u32()}, {2, ty.f32()}}); "ub_func", "foo_ub", {{0, ty.i32()}, {1, ty.u32()}, {2, ty.f32()}});
@ -1839,7 +1840,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleMembers) {
TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingPadding) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingPadding) {
ast::Struct* foo_struct_type = ast::Struct* foo_struct_type =
MakeUniformBufferType("foo_type", {ty.vec3<f32>()}); MakeUniformBufferType("foo_type", {ty.vec3<f32>()});
AddUniformBuffer("foo_ub", foo_struct_type, 0, 0); AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub",
{{0, ty.vec3<f32>()}}); {{0, ty.vec3<f32>()}});
@ -1866,9 +1867,9 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingPadding) {
TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleUniformBuffers) { TEST_F(InspectorGetUniformBufferResourceBindingsTest, MultipleUniformBuffers) {
ast::Struct* ub_struct_type = ast::Struct* ub_struct_type =
MakeUniformBufferType("ub_type", {ty.i32(), ty.u32(), ty.f32()}); MakeUniformBufferType("ub_type", {ty.i32(), ty.u32(), ty.f32()});
AddUniformBuffer("ub_foo", ub_struct_type, 0, 0); AddUniformBuffer("ub_foo", ty.Of(ub_struct_type), 0, 0);
AddUniformBuffer("ub_bar", ub_struct_type, 0, 1); AddUniformBuffer("ub_bar", ty.Of(ub_struct_type), 0, 1);
AddUniformBuffer("ub_baz", ub_struct_type, 2, 0); AddUniformBuffer("ub_baz", ty.Of(ub_struct_type), 2, 0);
auto AddReferenceFunc = [this](const std::string& func_name, auto AddReferenceFunc = [this](const std::string& func_name,
const std::string& var_name) { const std::string& var_name) {
@ -1924,7 +1925,7 @@ TEST_F(InspectorGetUniformBufferResourceBindingsTest, ContainingArray) {
// and will need to be fixed. // and will need to be fixed.
ast::Struct* foo_struct_type = ast::Struct* foo_struct_type =
MakeUniformBufferType("foo_type", {ty.i32(), ty.array<u32, 4>()}); MakeUniformBufferType("foo_type", {ty.i32(), ty.array<u32, 4>()});
AddUniformBuffer("foo_ub", foo_struct_type, 0, 0); AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}}); MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub", {{0, ty.i32()}});

View File

@ -110,6 +110,10 @@ const sem::Type* Program::TypeOf(const ast::Type* type) const {
return Sem().Get(type); return Sem().Get(type);
} }
const sem::Type* Program::TypeOf(const ast::TypeDecl* type_decl) const {
return Sem().Get(type_decl);
}
std::string Program::to_str(bool demangle) const { std::string Program::to_str(bool demangle) const {
AssertNotMoved(); AssertNotMoved();
auto str = ast_->to_str(Sem()); auto str = ast_->to_str(Sem());

View File

@ -132,10 +132,17 @@ class Program {
sem::Type* TypeOf(const ast::Expression* expr) const; sem::Type* TypeOf(const ast::Expression* expr) const;
/// Helper for returning the resolved semantic type of the AST type `type`. /// Helper for returning the resolved semantic type of the AST type `type`.
/// @param expr the AST type /// @param type the AST type
/// @return the resolved semantic type for the type, or nullptr if the type /// @return the resolved semantic type for the type, or nullptr if the type
/// has no resolved type. /// has no resolved type.
const sem::Type* TypeOf(const ast::Type* expr) const; const sem::Type* TypeOf(const ast::Type* type) const;
/// Helper for returning the resolved semantic type of the AST type
/// declaration `type_decl`.
/// @param type_decl the AST type declaration
/// @return the resolved semantic type for the type declaration, or nullptr if
/// the type declaration has no resolved type.
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const;
/// @param demangle whether to automatically demangle the symbols in the /// @param demangle whether to automatically demangle the symbols in the
/// returned string /// returned string

View File

@ -102,20 +102,17 @@ const sem::Type* ProgramBuilder::TypeOf(const ast::Type* type) const {
return Sem().Get(type); return Sem().Get(type);
} }
ast::Type* ProgramBuilder::TypesBuilder::MaybeCreateTypename( const sem::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const {
ast::Type* type) const { return Sem().Get(type_decl);
if (auto* nt = As<ast::NamedType>(type)) {
return type_name(nt->name());
}
return type;
} }
const ast::Type* ProgramBuilder::TypesBuilder::MaybeCreateTypename( ast::TypeName* ProgramBuilder::TypesBuilder::Of(ast::TypeDecl* decl) const {
const ast::Type* type) const { return type_name(decl->name());
if (auto* nt = As<ast::NamedType>(type)) { }
return type_name(nt->name());
} const ast::TypeName* ProgramBuilder::TypesBuilder::Of(
return type; const ast::TypeDecl* decl) const {
return type_name(decl->name());
} }
ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {} ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}

View File

@ -434,7 +434,6 @@ class ProgramBuilder {
/// @param n vector width in elements /// @param n vector width in elements
/// @return the tint AST type for a `n`-element vector of `type`. /// @return the tint AST type for a `n`-element vector of `type`.
ast::Vector* vec(ast::Type* type, uint32_t n) const { ast::Vector* vec(ast::Type* type, uint32_t n) const {
type = MaybeCreateTypename(type);
return builder->create<ast::Vector>(type, n); return builder->create<ast::Vector>(type, n);
} }
@ -443,7 +442,6 @@ class ProgramBuilder {
/// @param n vector width in elements /// @param n vector width in elements
/// @return the tint AST type for a `n`-element vector of `type`. /// @return the tint AST type for a `n`-element vector of `type`.
ast::Vector* vec(const Source& source, ast::Type* type, uint32_t n) const { ast::Vector* vec(const Source& source, ast::Type* type, uint32_t n) const {
type = MaybeCreateTypename(type);
return builder->create<ast::Vector>(source, type, n); return builder->create<ast::Vector>(source, type, n);
} }
@ -489,7 +487,6 @@ class ProgramBuilder {
/// @param rows number of rows for the matrix /// @param rows number of rows for the matrix
/// @return the tint AST type for a matrix of `type` /// @return the tint AST type for a matrix of `type`
ast::Matrix* mat(ast::Type* type, uint32_t columns, uint32_t rows) const { ast::Matrix* mat(ast::Type* type, uint32_t columns, uint32_t rows) const {
type = MaybeCreateTypename(type);
return builder->create<ast::Matrix>(type, rows, columns); return builder->create<ast::Matrix>(type, rows, columns);
} }
@ -610,7 +607,6 @@ class ProgramBuilder {
ast::Array* array(ast::Type* subtype, ast::Array* array(ast::Type* subtype,
uint32_t n = 0, uint32_t n = 0,
ast::DecorationList decos = {}) const { ast::DecorationList decos = {}) const {
subtype = MaybeCreateTypename(subtype);
return builder->create<ast::Array>(subtype, n, decos); return builder->create<ast::Array>(subtype, n, decos);
} }
@ -623,7 +619,6 @@ class ProgramBuilder {
ast::Type* subtype, ast::Type* subtype,
uint32_t n = 0, uint32_t n = 0,
ast::DecorationList decos = {}) const { ast::DecorationList decos = {}) const {
subtype = MaybeCreateTypename(subtype);
return builder->create<ast::Array>(source, subtype, n, decos); return builder->create<ast::Array>(source, subtype, n, decos);
} }
@ -632,7 +627,6 @@ class ProgramBuilder {
/// @param stride the array stride. 0 represents implicit stride /// @param stride the array stride. 0 represents implicit stride
/// @return the tint AST type for a array of size `n` of type `T` /// @return the tint AST type for a array of size `n` of type `T`
ast::Array* array(ast::Type* subtype, uint32_t n, uint32_t stride) const { ast::Array* array(ast::Type* subtype, uint32_t n, uint32_t stride) const {
subtype = MaybeCreateTypename(subtype);
ast::DecorationList decos; ast::DecorationList decos;
if (stride) { if (stride) {
decos.emplace_back(builder->create<ast::StrideDecoration>(stride)); decos.emplace_back(builder->create<ast::StrideDecoration>(stride));
@ -649,7 +643,6 @@ class ProgramBuilder {
ast::Type* subtype, ast::Type* subtype,
uint32_t n, uint32_t n,
uint32_t stride) const { uint32_t stride) const {
subtype = MaybeCreateTypename(subtype);
ast::DecorationList decos; ast::DecorationList decos;
if (stride) { if (stride) {
decos.emplace_back(builder->create<ast::StrideDecoration>(stride)); decos.emplace_back(builder->create<ast::StrideDecoration>(stride));
@ -695,7 +688,6 @@ class ProgramBuilder {
/// @returns the alias pointer /// @returns the alias pointer
template <typename NAME> template <typename NAME>
ast::Alias* alias(NAME&& name, ast::Type* type) const { ast::Alias* alias(NAME&& name, ast::Type* type) const {
type = MaybeCreateTypename(type);
auto sym = builder->Sym(std::forward<NAME>(name)); auto sym = builder->Sym(std::forward<NAME>(name));
return builder->create<ast::Alias>(sym, type); return builder->create<ast::Alias>(sym, type);
} }
@ -709,7 +701,6 @@ class ProgramBuilder {
ast::Alias* alias(const Source& source, ast::Alias* alias(const Source& source,
NAME&& name, NAME&& name,
ast::Type* type) const { ast::Type* type) const {
type = MaybeCreateTypename(type);
auto sym = builder->Sym(std::forward<NAME>(name)); auto sym = builder->Sym(std::forward<NAME>(name));
return builder->create<ast::Alias>(source, sym, type); return builder->create<ast::Alias>(source, sym, type);
} }
@ -721,7 +712,6 @@ class ProgramBuilder {
ast::Pointer* pointer(ast::Type* type, ast::Pointer* pointer(ast::Type* type,
ast::StorageClass storage_class, ast::StorageClass storage_class,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
type = MaybeCreateTypename(type);
return builder->create<ast::Pointer>(type, storage_class, access); return builder->create<ast::Pointer>(type, storage_class, access);
} }
@ -734,7 +724,6 @@ class ProgramBuilder {
ast::Type* type, ast::Type* type,
ast::StorageClass storage_class, ast::StorageClass storage_class,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
type = MaybeCreateTypename(type);
return builder->create<ast::Pointer>(source, type, storage_class, access); return builder->create<ast::Pointer>(source, type, storage_class, access);
} }
@ -848,17 +837,15 @@ class ProgramBuilder {
} }
/// [DEPRECATED]: TODO(crbug.com/tint/745): Migrate to const AST pointers. /// [DEPRECATED]: TODO(crbug.com/tint/745): Migrate to const AST pointers.
/// If ty is a ast::Struct or ast::Alias, the returned type is an /// Constructs a TypeName for the type declaration.
/// ast::TypeName of the given type's name, otherwise type is returned.
/// @param type the type /// @param type the type
/// @return either type or a pointer to a new ast::TypeName /// @return either type or a pointer to a new ast::TypeName
ast::Type* MaybeCreateTypename(ast::Type* type) const; ast::TypeName* Of(ast::TypeDecl* type) const;
/// If ty is a ast::Struct or ast::Alias, the returned type is an /// Constructs a TypeName for the type declaration.
/// ast::TypeName of the given type's name, otherwise type is returned.
/// @param type the type /// @param type the type
/// @return either type or a pointer to a new ast::TypeName /// @return either type or a pointer to a new ast::TypeName
const ast::Type* MaybeCreateTypename(const ast::Type* type) const; const ast::TypeName* Of(const ast::TypeDecl* type) const;
/// The ProgramBuilder /// The ProgramBuilder
ProgramBuilder* const builder; ProgramBuilder* const builder;
@ -1073,7 +1060,6 @@ class ProgramBuilder {
/// values `args`. /// values `args`.
template <typename... ARGS> template <typename... ARGS>
ast::TypeConstructorExpression* Construct(ast::Type* type, ARGS&&... args) { ast::TypeConstructorExpression* Construct(ast::Type* type, ARGS&&... args) {
type = ty.MaybeCreateTypename(type);
return create<ast::TypeConstructorExpression>( return create<ast::TypeConstructorExpression>(
type, ExprList(std::forward<ARGS>(args)...)); type, ExprList(std::forward<ARGS>(args)...));
} }
@ -1210,7 +1196,6 @@ class ProgramBuilder {
ast::Variable* Var(NAME&& name, ast::Variable* Var(NAME&& name,
const ast::Type* type, const ast::Type* type,
OPTIONAL&&... optional) { OPTIONAL&&... optional) {
type = ty.MaybeCreateTypename(type);
VarOptionals opts(std::forward<OPTIONAL>(optional)...); VarOptionals opts(std::forward<OPTIONAL>(optional)...);
return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage, return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage,
opts.access, type, false, opts.constructor, opts.access, type, false, opts.constructor,
@ -1234,7 +1219,6 @@ class ProgramBuilder {
NAME&& name, NAME&& name,
const ast::Type* type, const ast::Type* type,
OPTIONAL&&... optional) { OPTIONAL&&... optional) {
type = ty.MaybeCreateTypename(type);
VarOptionals opts(std::forward<OPTIONAL>(optional)...); VarOptionals opts(std::forward<OPTIONAL>(optional)...);
return create<ast::Variable>(source, Sym(std::forward<NAME>(name)), return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
opts.storage, opts.access, type, false, opts.storage, opts.access, type, false,
@ -1251,7 +1235,6 @@ class ProgramBuilder {
ast::Type* type, ast::Type* type,
ast::Expression* constructor, ast::Expression* constructor,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::Variable>( return create<ast::Variable>(
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, constructor, decorations); ast::Access::kUndefined, type, true, constructor, decorations);
@ -1269,7 +1252,6 @@ class ProgramBuilder {
ast::Type* type, ast::Type* type,
ast::Expression* constructor, ast::Expression* constructor,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::Variable>( return create<ast::Variable>(
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, constructor, decorations); ast::Access::kUndefined, type, true, constructor, decorations);
@ -1283,7 +1265,6 @@ class ProgramBuilder {
ast::Variable* Param(NAME&& name, ast::Variable* Param(NAME&& name,
ast::Type* type, ast::Type* type,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::Variable>( return create<ast::Variable>(
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, nullptr, decorations); ast::Access::kUndefined, type, true, nullptr, decorations);
@ -1299,7 +1280,6 @@ class ProgramBuilder {
NAME&& name, NAME&& name,
ast::Type* type, ast::Type* type,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::Variable>( return create<ast::Variable>(
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, nullptr, decorations); ast::Access::kUndefined, type, true, nullptr, decorations);
@ -1559,7 +1539,6 @@ class ProgramBuilder {
ast::StatementList body, ast::StatementList body,
ast::DecorationList decorations = {}, ast::DecorationList decorations = {},
ast::DecorationList return_type_decorations = {}) { ast::DecorationList return_type_decorations = {}) {
type = ty.MaybeCreateTypename(type);
auto* func = auto* func =
create<ast::Function>(source, Sym(std::forward<NAME>(name)), params, create<ast::Function>(source, Sym(std::forward<NAME>(name)), params,
type, create<ast::BlockStatement>(body), type, create<ast::BlockStatement>(body),
@ -1584,7 +1563,6 @@ class ProgramBuilder {
ast::StatementList body, ast::StatementList body,
ast::DecorationList decorations = {}, ast::DecorationList decorations = {},
ast::DecorationList return_type_decorations = {}) { ast::DecorationList return_type_decorations = {}) {
type = ty.MaybeCreateTypename(type);
auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params, auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params,
type, create<ast::BlockStatement>(body), type, create<ast::BlockStatement>(body),
decorations, return_type_decorations); decorations, return_type_decorations);
@ -1688,7 +1666,6 @@ class ProgramBuilder {
NAME&& name, NAME&& name,
ast::Type* type, ast::Type* type,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)),
type, std::move(decorations)); type, std::move(decorations));
} }
@ -1702,7 +1679,6 @@ class ProgramBuilder {
ast::StructMember* Member(NAME&& name, ast::StructMember* Member(NAME&& name,
ast::Type* type, ast::Type* type,
ast::DecorationList decorations = {}) { ast::DecorationList decorations = {}) {
type = ty.MaybeCreateTypename(type);
return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)),
type, std::move(decorations)); type, std::move(decorations));
} }
@ -1714,7 +1690,6 @@ class ProgramBuilder {
/// @returns the struct member pointer /// @returns the struct member pointer
template <typename NAME> template <typename NAME>
ast::StructMember* Member(uint32_t offset, NAME&& name, ast::Type* type) { ast::StructMember* Member(uint32_t offset, NAME&& name, ast::Type* type) {
type = ty.MaybeCreateTypename(type);
return create<ast::StructMember>( return create<ast::StructMember>(
source_, Sym(std::forward<NAME>(name)), type, source_, Sym(std::forward<NAME>(name)), type,
ast::DecorationList{ ast::DecorationList{
@ -1978,10 +1953,19 @@ class ProgramBuilder {
/// Helper for returning the resolved semantic type of the AST type `type`. /// Helper for returning the resolved semantic type of the AST type `type`.
/// @note As the Resolver is run when the Program is built, this will only be /// @note As the Resolver is run when the Program is built, this will only be
/// useful for the Resolver itself and tests that use their own Resolver. /// useful for the Resolver itself and tests that use their own Resolver.
/// @param expr the AST type /// @param type the AST type
/// @return the resolved semantic type for the type, or nullptr if the type /// @return the resolved semantic type for the type, or nullptr if the type
/// has no resolved type. /// has no resolved type.
const sem::Type* TypeOf(const ast::Type* expr) const; const sem::Type* TypeOf(const ast::Type* type) const;
/// Helper for returning the resolved semantic type of the AST type
/// declaration `type_decl`.
/// @note As the Resolver is run when the Program is built, this will only be
/// useful for the Resolver itself and tests that use their own Resolver.
/// @param type_decl the AST type declaration
/// @return the resolved semantic type for the type declaration, or nullptr if
/// the type declaration has no resolved type.
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const;
/// Wraps the ast::Literal in a statement. This is used by tests that /// Wraps the ast::Literal in a statement. This is used by tests that
/// construct a partial AST and require the Resolver to reach these /// construct a partial AST and require the Resolver to reach these

View File

@ -1042,10 +1042,10 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
} }
// Create and register the result type. // Create and register the result type.
return_type = create<ast::Struct>(Source{}, return_struct_sym, auto* str = create<ast::Struct>(Source{}, return_struct_sym, return_members,
return_members, ast::DecorationList{}); ast::DecorationList{});
parser_impl_.AddConstructedType(return_struct_sym, parser_impl_.AddConstructedType(return_struct_sym, str);
return_type->As<ast::NamedType>()); return_type = builder_.ty.Of(str);
// Add the return-value statement. // Add the return-value statement.
stmts.push_back(create<ast::ReturnStatement>( stmts.push_back(create<ast::ReturnStatement>(

View File

@ -1037,10 +1037,10 @@ const Type* ParserImpl::ConvertType(
return ty_.Struct(sym, std::move(ast_member_types)); return ty_.Struct(sym, std::move(ast_member_types));
} }
void ParserImpl::AddConstructedType(Symbol name, ast::NamedType* type) { void ParserImpl::AddConstructedType(Symbol name, ast::TypeDecl* decl) {
auto iter = constructed_types_.insert(name); auto iter = constructed_types_.insert(name);
if (iter.second) { if (iter.second) {
builder_.AST().AddConstructedType(type); builder_.AST().AddConstructedType(decl);
} }
} }

View File

@ -192,8 +192,8 @@ class ParserImpl : Reader {
/// Adds `type` as a constructed type if it hasn't been added yet. /// Adds `type` as a constructed type if it hasn't been added yet.
/// @param name the type's unique name /// @param name the type's unique name
/// @param type the type to add /// @param decl the type declaration to add
void AddConstructedType(Symbol name, ast::NamedType* type); void AddConstructedType(Symbol name, ast::TypeDecl* decl);
/// @returns the fail stream object /// @returns the fail stream object
FailStream& fail_stream() { return fail_stream_; } FailStream& fail_stream() { return fail_stream_; }

View File

@ -4085,7 +4085,7 @@ TEST_F(SpvModuleScopeVarParserTest, EntryPointWrapping_IOLocations) {
{ {
Return{} Return{}
} }
Function main -> __struct_main_out Function main -> __type_name_main_out
StageDecoration{vertex} StageDecoration{vertex}
( (
VariableConst{ VariableConst{
@ -4124,7 +4124,7 @@ TEST_F(SpvModuleScopeVarParserTest, EntryPointWrapping_IOLocations) {
Return{ Return{
{ {
TypeConstructor[not set]{ TypeConstructor[not set]{
__struct_main_out __type_name_main_out
Identifier[not set]{x_2} Identifier[not set]{x_2}
Identifier[not set]{x_4} Identifier[not set]{x_4}
} }

View File

@ -313,11 +313,11 @@ Token ParserImpl::last_token() const {
} }
void ParserImpl::register_constructed(const std::string& name, void ParserImpl::register_constructed(const std::string& name,
const ast::Type* type) { const ast::TypeDecl* type_decl) {
registered_constructs_[name] = type; registered_constructs_[name] = type_decl;
} }
const ast::Type* ParserImpl::get_constructed(const std::string& name) { const ast::TypeDecl* ParserImpl::get_constructed(const std::string& name) {
if (registered_constructs_.find(name) == registered_constructs_.end()) { if (registered_constructs_.find(name) == registered_constructs_.end()) {
return nullptr; return nullptr;
} }

View File

@ -381,13 +381,14 @@ class ParserImpl {
/// Registers a constructed type into the parser /// Registers a constructed type into the parser
/// TODO(crbug.com/tint/724): Remove /// TODO(crbug.com/tint/724): Remove
/// @param name the constructed name /// @param name the constructed name
/// @param type the constructed type /// @param type_decl the constructed type declaration
void register_constructed(const std::string& name, const ast::Type* type); void register_constructed(const std::string& name,
const ast::TypeDecl* type_decl);
/// Retrieves a constructed type /// Retrieves a constructed type
/// TODO(crbug.com/tint/724): Remove /// TODO(crbug.com/tint/724): Remove
/// @param name The name to lookup /// @param name The name to lookup
/// @returns the constructed type for `name` or `nullptr` if not found /// @returns the constructed type for `name` or `nullptr` if not found
const ast::Type* get_constructed(const std::string& name); const ast::TypeDecl* get_constructed(const std::string& name);
/// Parses the `translation_unit` grammar element /// Parses the `translation_unit` grammar element
void translation_unit(); void translation_unit();
@ -881,7 +882,7 @@ class ParserImpl {
uint32_t sync_depth_ = 0; uint32_t sync_depth_ = 0;
std::vector<Token::Type> sync_tokens_; std::vector<Token::Type> sync_tokens_;
int silence_errors_ = 0; int silence_errors_ = 0;
std::unordered_map<std::string, const ast::Type*> registered_constructs_; std::unordered_map<std::string, const ast::TypeDecl*> registered_constructs_;
ProgramBuilder builder_; ProgramBuilder builder_;
size_t max_errors_ = 25; size_t max_errors_ = 25;
}; };

View File

@ -53,11 +53,11 @@ fn main() -> { // missing return type
TEST_F(ParserImplTest, GetRegisteredType) { TEST_F(ParserImplTest, GetRegisteredType) {
auto p = parser(""); auto p = parser("");
p->register_constructed("my_alias", ty.i32()); auto* alias = create<ast::Alias>(Sym("my_alias"), ty.i32());
p->register_constructed("my_alias", alias);
auto* alias = p->get_constructed("my_alias"); auto* got = p->get_constructed("my_alias");
ASSERT_NE(alias, nullptr); EXPECT_EQ(got, alias);
EXPECT_TRUE(alias->Is<ast::I32>());
} }
TEST_F(ParserImplTest, GetUnregisteredType) { TEST_F(ParserImplTest, GetUnregisteredType) {

View File

@ -112,7 +112,7 @@ TEST_F(ResolverAssignmentValidationTest,
// var a : myint = 2; // var a : myint = 2;
// a = 2 // a = 2
auto* myint = Alias("myint", ty.i32()); auto* myint = Alias("myint", ty.i32());
auto* var = Var("a", myint, ast::StorageClass::kNone, Expr(2)); auto* var = Var("a", ty.Of(myint), ast::StorageClass::kNone, Expr(2));
WrapInFunction(var, Assign(Source{{12, 34}}, "a", 2)); WrapInFunction(var, Assign(Source{{12, 34}}, "a", 2));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -295,7 +295,7 @@ TEST_F(ResolverControlBlockValidationTest, SwitchCaseAlias_Pass) {
// } // }
auto* my_int = Alias("MyInt", ty.u32()); auto* my_int = Alias("MyInt", ty.u32());
auto* var = Var("a", my_int, ast::StorageClass::kNone, Expr(2u)); auto* var = Var("a", ty.Of(my_int), ast::StorageClass::kNone, Expr(2u));
ast::CaseSelectorList default_csl; ast::CaseSelectorList default_csl;
auto* block_default = Block(); auto* block_default = Block();

View File

@ -509,7 +509,7 @@ using StructBlockTest = ResolverTest;
TEST_F(StructBlockTest, StructUsedAsArrayElement) { TEST_F(StructBlockTest, StructUsedAsArrayElement) {
auto* s = Structure("S", {Member("x", ty.i32())}, auto* s = Structure("S", {Member("x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* a = ty.array(s, 4); auto* a = ty.array(ty.Of(s), 4);
Global("G", a, ast::StorageClass::kPrivate); Global("G", a, ast::StorageClass::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -528,7 +528,7 @@ using ResourceDecorationTest = ResolverTest;
TEST_F(ResourceDecorationTest, UniformBufferMissingBinding) { TEST_F(ResourceDecorationTest, UniformBufferMissingBinding) {
auto* s = Structure("S", {Member("x", ty.i32())}, auto* s = Structure("S", {Member("x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{12, 34}}, "G", s, ast::StorageClass::kUniform); Global(Source{{12, 34}}, "G", ty.Of(s), ast::StorageClass::kUniform);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -539,7 +539,7 @@ TEST_F(ResourceDecorationTest, UniformBufferMissingBinding) {
TEST_F(ResourceDecorationTest, StorageBufferMissingBinding) { TEST_F(ResourceDecorationTest, StorageBufferMissingBinding) {
auto* s = Structure("S", {Member("x", ty.i32())}, auto* s = Structure("S", {Member("x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{12, 34}}, "G", s, ast::StorageClass::kStorage, Global(Source{{12, 34}}, "G", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead); ast::Access::kRead);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -108,8 +108,9 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Struct) {
// return Output(); // return Output();
// } // }
auto* output = Structure("Output", {}); auto* output = Structure("Output", {});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Stage(ast::PipelineStage::kVertex)}, {Location(Source{{13, 43}}, 0)}); {Return(Construct(ty.Of(output)))}, {Stage(ast::PipelineStage::kVertex)},
{Location(Source{{13, 43}}, 0)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
@ -130,7 +131,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_Valid) {
auto* output = Structure( auto* output = Structure(
"Output", {Member("a", ty.f32(), {Location(0)}), "Output", {Member("a", ty.f32(), {Location(0)}),
Member("b", ty.f32(), {Builtin(ast::Builtin::kFragDepth)})}); Member("b", ty.f32(), {Builtin(ast::Builtin::kFragDepth)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -150,7 +152,8 @@ TEST_F(ResolverEntryPointValidationTest,
{Member("a", ty.f32(), {Member("a", ty.f32(),
{Location(Source{{13, 43}}, 0), {Location(Source{{13, 43}}, 0),
Builtin(Source{{14, 52}}, ast::Builtin::kFragDepth)})}); Builtin(Source{{14, 52}}, ast::Builtin::kFragDepth)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -172,7 +175,8 @@ TEST_F(ResolverEntryPointValidationTest,
auto* output = Structure( auto* output = Structure(
"Output", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)}), "Output", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)}),
Member(Source{{14, 52}}, "b", ty.f32(), {})}); Member(Source{{14, 52}}, "b", ty.f32(), {})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -195,8 +199,9 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_NestedStruct) {
auto* inner = Structure( auto* inner = Structure(
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})}); "Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
auto* output = Structure( auto* output = Structure(
"Output", {Member(Source{{14, 52}}, "a", inner, {Location(0)})}); "Output", {Member(Source{{14, 52}}, "a", ty.Of(inner), {Location(0)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -219,7 +224,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_RuntimeArray) {
"Output", "Output",
{Member(Source{{13, 43}}, "a", ty.array<float>(), {Location(0)})}, {Member(Source{{13, 43}}, "a", ty.array<float>(), {Location(0)})},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -241,7 +247,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateBuiltins) {
auto* output = Structure( auto* output = Structure(
"Output", {Member("a", ty.f32(), {Builtin(ast::Builtin::kFragDepth)}), "Output", {Member("a", ty.f32(), {Builtin(ast::Builtin::kFragDepth)}),
Member("b", ty.f32(), {Builtin(ast::Builtin::kFragDepth)})}); Member("b", ty.f32(), {Builtin(ast::Builtin::kFragDepth)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -262,7 +269,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateLocation) {
// } // }
auto* output = Structure("Output", {Member("a", ty.f32(), {Location(1)}), auto* output = Structure("Output", {Member("a", ty.f32(), {Location(1)}),
Member("b", ty.f32(), {Location(1)})}); Member("b", ty.f32(), {Location(1)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -325,7 +333,7 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Struct) {
// [[stage(fragment)]] // [[stage(fragment)]]
// fn main([[location(0)]] param : Input) {} // fn main([[location(0)]] param : Input) {}
auto* input = Structure("Input", {}); auto* input = Structure("Input", {});
auto* param = Param("param", input, {Location(Source{{13, 43}}, 0)}); auto* param = Param("param", ty.Of(input), {Location(Source{{13, 43}}, 0)});
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -346,7 +354,7 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_Valid) {
auto* input = Structure( auto* input = Structure(
"Input", {Member("a", ty.f32(), {Location(0)}), "Input", {Member("a", ty.f32(), {Location(0)}),
Member("b", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})}); Member("b", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})});
auto* param = Param("param", input); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -365,7 +373,7 @@ TEST_F(ResolverEntryPointValidationTest,
{Member("a", ty.f32(), {Member("a", ty.f32(),
{Location(Source{{13, 43}}, 0), {Location(Source{{13, 43}}, 0),
Builtin(Source{{14, 52}}, ast::Builtin::kSampleIndex)})}); Builtin(Source{{14, 52}}, ast::Builtin::kSampleIndex)})});
auto* param = Param("param", input); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -386,7 +394,7 @@ TEST_F(ResolverEntryPointValidationTest,
auto* input = Structure( auto* input = Structure(
"Input", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)}), "Input", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)}),
Member(Source{{14, 52}}, "b", ty.f32(), {})}); Member(Source{{14, 52}}, "b", ty.f32(), {})});
auto* param = Param("param", input); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -406,9 +414,9 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_NestedStruct) {
// fn main(param : Input) {} // fn main(param : Input) {}
auto* inner = Structure( auto* inner = Structure(
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})}); "Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
auto* input = auto* input = Structure(
Structure("Input", {Member(Source{{14, 52}}, "a", inner, {Location(0)})}); "Input", {Member(Source{{14, 52}}, "a", ty.Of(inner), {Location(0)})});
auto* param = Param("param", input); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -430,7 +438,7 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_RuntimeArray) {
"Input", "Input",
{Member(Source{{13, 43}}, "a", ty.array<float>(), {Location(0)})}, {Member(Source{{13, 43}}, "a", ty.array<float>(), {Location(0)})},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* param = Param("param", input); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -472,8 +480,8 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) {
"InputA", {Member("a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})}); "InputA", {Member("a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})});
auto* input_b = Structure( auto* input_b = Structure(
"InputB", {Member("a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})}); "InputB", {Member("a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})});
auto* param_a = Param("param_a", input_a); auto* param_a = Param("param_a", ty.Of(input_a));
auto* param_b = Param("param_b", input_b); auto* param_b = Param("param_b", ty.Of(input_b));
Func(Source{{12, 34}}, "main", {param_a, param_b}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param_a, param_b}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -510,8 +518,8 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateLocation) {
// fn main(param_a : InputA, param_b : InputB) {} // fn main(param_a : InputA, param_b : InputB) {}
auto* input_a = Structure("InputA", {Member("a", ty.f32(), {Location(1)})}); auto* input_a = Structure("InputA", {Member("a", ty.f32(), {Location(1)})});
auto* input_b = Structure("InputB", {Member("a", ty.f32(), {Location(1)})}); auto* input_b = Structure("InputB", {Member("a", ty.f32(), {Location(1)})});
auto* param_a = Param("param_a", input_a); auto* param_a = Param("param_a", ty.Of(input_a));
auto* param_b = Param("param_b", input_b); auto* param_b = Param("param_b", ty.Of(input_b));
Func(Source{{12, 34}}, "main", {param_a, param_b}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param_a, param_b}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -599,7 +607,7 @@ TEST_P(TypeValidationTest, StructInputs) {
auto params = GetParam(); auto params = GetParam();
auto* input = Structure( auto* input = Structure(
"Input", {Member("a", params.create_ast_type(*this), {Location(0)})}); "Input", {Member("a", params.create_ast_type(*this), {Location(0)})});
auto* a = Param("a", input, {}); auto* a = Param("a", ty.Of(input), {});
Func(Source{{12, 34}}, "main", {a}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {a}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
@ -638,7 +646,8 @@ TEST_P(TypeValidationTest, StructOutputs) {
auto params = GetParam(); auto params = GetParam();
auto* output = Structure( auto* output = Structure(
"Output", {Member("a", params.create_ast_type(*this), {Location(0)})}); "Output", {Member("a", params.create_ast_type(*this), {Location(0)})});
Func(Source{{12, 34}}, "main", {}, output, {Return(Construct(output))}, Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
if (params.is_valid) { if (params.is_valid) {

View File

@ -231,7 +231,7 @@ TEST_F(ResolverFunctionValidationTest,
// type myf32 = f32; // type myf32 = f32;
// fn func -> myf32 { return 2.0; } // fn func -> myf32 { return 2.0; }
auto* myf32 = Alias("myf32", ty.f32()); auto* myf32 = Alias("myf32", ty.f32());
Func("func", ast::VariableList{}, myf32, Func("func", ast::VariableList{}, ty.Of(myf32),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2.f)), Return(Source{Source::Location{12, 34}}, Expr(2.f)),
}, },
@ -245,7 +245,7 @@ TEST_F(ResolverFunctionValidationTest,
// type myf32 = f32; // type myf32 = f32;
// fn func -> myf32 { return 2; } // fn func -> myf32 { return 2; }
auto* myf32 = Alias("myf32", ty.f32()); auto* myf32 = Alias("myf32", ty.f32());
Func("func", ast::VariableList{}, myf32, Func("func", ast::VariableList{}, ty.Of(myf32),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2u)), Return(Source{Source::Location{12, 34}}, Expr(2u)),
}, },

View File

@ -29,7 +29,7 @@ TEST_F(ResolverHostShareableValidationTest, BoolMember) {
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.bool_())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.bool_())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -49,7 +49,7 @@ TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) {
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.vec3<bool>())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.vec3<bool>())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -67,10 +67,10 @@ TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) {
TEST_F(ResolverHostShareableValidationTest, Aliases) { TEST_F(ResolverHostShareableValidationTest, Aliases) {
auto* a1 = Alias("a1", ty.bool_()); auto* a1 = Alias("a1", ty.bool_());
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", a1)}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.Of(a1))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* a2 = Alias("a2", s); auto* a2 = Alias("a2", ty.Of(s));
Global(Source{{56, 78}}, "g", a2, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -88,13 +88,13 @@ TEST_F(ResolverHostShareableValidationTest, Aliases) {
TEST_F(ResolverHostShareableValidationTest, NestedStructures) { TEST_F(ResolverHostShareableValidationTest, NestedStructures) {
auto* i1 = Structure("I1", {Member(Source{{1, 2}}, "x", ty.bool_())}); auto* i1 = Structure("I1", {Member(Source{{1, 2}}, "x", ty.bool_())});
auto* i2 = Structure("I2", {Member(Source{{3, 4}}, "y", i1)}); auto* i2 = Structure("I2", {Member(Source{{3, 4}}, "y", ty.Of(i1))});
auto* i3 = Structure("I3", {Member(Source{{5, 6}}, "z", i2)}); auto* i3 = Structure("I3", {Member(Source{{5, 6}}, "z", ty.Of(i2))});
auto* s = Structure("S", {Member(Source{{7, 8}}, "m", i3)}, auto* s = Structure("S", {Member(Source{{7, 8}}, "m", ty.Of(i3))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{9, 10}}, "g", s, ast::StorageClass::kStorage, Global(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -120,22 +120,22 @@ TEST_F(ResolverHostShareableValidationTest, NoError) {
Member(Source{{2, 1}}, "y1", ty.vec3<f32>()), Member(Source{{2, 1}}, "y1", ty.vec3<f32>()),
Member(Source{{3, 1}}, "z1", ty.array<i32, 4>()), Member(Source{{3, 1}}, "z1", ty.array<i32, 4>()),
}); });
auto* a1 = Alias("a1", i1); auto* a1 = Alias("a1", ty.Of(i1));
auto* i2 = Structure("I2", { auto* i2 = Structure("I2", {
Member(Source{{4, 1}}, "x2", ty.mat2x2<f32>()), Member(Source{{4, 1}}, "x2", ty.mat2x2<f32>()),
Member(Source{{5, 1}}, "y2", i1), Member(Source{{5, 1}}, "y2", ty.Of(i1)),
}); });
auto* a2 = Alias("a2", i2); auto* a2 = Alias("a2", ty.Of(i2));
auto* i3 = Structure("I3", { auto* i3 = Structure("I3", {
Member(Source{{4, 1}}, "x3", a1), Member(Source{{4, 1}}, "x3", ty.Of(a1)),
Member(Source{{5, 1}}, "y3", i2), Member(Source{{5, 1}}, "y3", ty.Of(i2)),
Member(Source{{6, 1}}, "z3", a2), Member(Source{{6, 1}}, "z3", ty.Of(a2)),
}); });
auto* s = Structure("S", {Member(Source{{7, 8}}, "m", i3)}, auto* s = Structure("S", {Member(Source{{7, 8}}, "m", ty.Of(i3))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{9, 10}}, "g", s, ast::StorageClass::kStorage, Global(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),

View File

@ -158,15 +158,15 @@ TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
TEST_F(ResolverInferredTypeTest, InferStruct_Pass) { TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
auto* member = Member("x", ty.i32()); auto* member = Member("x", ty.i32());
auto* type = Structure("S", {member}, {create<ast::StructBlockDecoration>()}); auto* str = Structure("S", {member}, {create<ast::StructBlockDecoration>()});
auto* expected_type = auto* expected_type =
create<sem::Struct>(type, create<sem::Struct>(str,
sem::StructMemberList{create<sem::StructMember>( sem::StructMemberList{create<sem::StructMember>(
member, create<sem::I32>(), 0, 0, 0, 4)}, member, create<sem::I32>(), 0, 0, 0, 4)},
0, 4, 4); 0, 4, 4);
auto* ctor_expr = Construct(type); auto* ctor_expr = Construct(ty.Of(str));
auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr); auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
WrapInFunction(var); WrapInFunction(var);

View File

@ -768,7 +768,7 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) {
auto* ary = ty.array<i32>(); auto* ary = ty.array<i32>();
auto* str = Structure("S", {Member("x", ary)}, auto* str = Structure("S", {Member("x", ary)},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("a", str, ast::StorageClass::kStorage, ast::Access::kRead, Global("a", ty.Of(str), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -105,7 +105,7 @@ TEST_F(ResolverIsStorableTest, Struct_NestedStorable) {
}); });
Structure("S", { Structure("S", {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", storable), Member("b", ty.Of(storable)),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -120,7 +120,7 @@ TEST_F(ResolverIsStorableTest, Struct_NestedNonStorable) {
}); });
Structure("S", { Structure("S", {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", non_storable), Member("b", ty.Of(non_storable)),
}); });
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -66,12 +66,12 @@ TEST_F(ResolverPtrRefTest, DefaultPtrStorageClass) {
auto* function = Var("f", ty.i32()); auto* function = Var("f", ty.i32());
auto* private_ = Global("p", ty.i32(), ast::StorageClass::kPrivate); auto* private_ = Global("p", ty.i32(), ast::StorageClass::kPrivate);
auto* workgroup = Global("w", ty.i32(), ast::StorageClass::kWorkgroup); auto* workgroup = Global("w", ty.i32(), ast::StorageClass::kWorkgroup);
auto* uniform = Global("ub", buf, ast::StorageClass::kUniform, auto* uniform = Global("ub", ty.Of(buf), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* storage = Global("sb", buf, ast::StorageClass::kStorage, auto* storage = Global("sb", ty.Of(buf), ast::StorageClass::kStorage,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -87,10 +87,10 @@ TEST_F(ResolverPtrRefTest, DefaultPtrStorageClass) {
Const("w_ptr", ty.pointer(ty.i32(), ast::StorageClass::kWorkgroup), Const("w_ptr", ty.pointer(ty.i32(), ast::StorageClass::kWorkgroup),
AddressOf(workgroup)); AddressOf(workgroup));
auto* uniform_ptr = auto* uniform_ptr =
Const("ub_ptr", ty.pointer(buf, ast::StorageClass::kUniform), Const("ub_ptr", ty.pointer(ty.Of(buf), ast::StorageClass::kUniform),
AddressOf(uniform)); AddressOf(uniform));
auto* storage_ptr = auto* storage_ptr =
Const("sb_ptr", ty.pointer(buf, ast::StorageClass::kStorage), Const("sb_ptr", ty.pointer(ty.Of(buf), ast::StorageClass::kStorage),
AddressOf(storage)); AddressOf(storage));
WrapInFunction(function, function_ptr, private_ptr, workgroup_ptr, WrapInFunction(function, function_ptr, private_ptr, workgroup_ptr,

View File

@ -90,14 +90,14 @@ TEST_F(ResolverPtrRefValidationTest, InferredPtrAccessMismatch) {
// let p : pointer<storage, i32> = &s.inner.arr[2]; // let p : pointer<storage, i32> = &s.inner.arr[2];
// } // }
auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())}); auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", {Member("inner", inner)}, auto* buf = Structure("S", {Member("inner", ty.Of(inner))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* storage = auto* storage = Global("s", ty.Of(buf), ast::StorageClass::kStorage,
Global("s", buf, ast::StorageClass::kStorage, ast::Access::kReadWrite, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* expr = auto* expr =
IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4); IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4);

View File

@ -213,9 +213,9 @@ bool Resolver::ResolveInternal() {
// Process everything else in the order they appear in the module. This is // Process everything else in the order they appear in the module. This is
// necessary for validation of use-before-declaration. // necessary for validation of use-before-declaration.
for (auto* decl : builder_->AST().GlobalDeclarations()) { for (auto* decl : builder_->AST().GlobalDeclarations()) {
if (auto* ty = decl->As<ast::NamedType>()) { if (auto* td = decl->As<ast::TypeDecl>()) {
Mark(ty); Mark(td);
if (!NamedType(ty)) { if (!TypeDecl(td)) {
return false; return false;
} }
} else if (auto* func = decl->As<ast::Function>()) { } else if (auto* func = decl->As<ast::Function>()) {
@ -2418,14 +2418,14 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
return true; return true;
} }
sem::Type* Resolver::NamedType(const ast::NamedType* named_type) { sem::Type* Resolver::TypeDecl(const ast::TypeDecl* named_type) {
sem::Type* result = nullptr; sem::Type* result = nullptr;
if (auto* alias = named_type->As<ast::Alias>()) { if (auto* alias = named_type->As<ast::Alias>()) {
result = Type(alias->type()); result = Type(alias->type());
} else if (auto* str = named_type->As<ast::Struct>()) { } else if (auto* str = named_type->As<ast::Struct>()) {
result = Structure(str); result = Structure(str);
} else { } else {
TINT_UNREACHABLE(diagnostics_) << "Unhandled NamedType"; TINT_UNREACHABLE(diagnostics_) << "Unhandled TypeDecl";
} }
if (!result) { if (!result) {
@ -2433,9 +2433,9 @@ sem::Type* Resolver::NamedType(const ast::NamedType* named_type) {
} }
named_type_info_.emplace(named_type->name(), named_type_info_.emplace(named_type->name(),
NamedTypeInfo{named_type, result}); TypeDeclInfo{named_type, result});
if (!ValidateNamedType(named_type)) { if (!ValidateTypeDecl(named_type)) {
return nullptr; return nullptr;
} }
@ -2443,10 +2443,10 @@ sem::Type* Resolver::NamedType(const ast::NamedType* named_type) {
return result; return result;
} }
bool Resolver::ValidateNamedType(const ast::NamedType* named_type) const { bool Resolver::ValidateTypeDecl(const ast::TypeDecl* named_type) const {
auto iter = named_type_info_.find(named_type->name()); auto iter = named_type_info_.find(named_type->name());
if (iter == named_type_info_.end()) { if (iter == named_type_info_.end()) {
TINT_ICE(diagnostics_) << "ValidateNamedType called() before NamedType()"; TINT_ICE(diagnostics_) << "ValidateTypeDecl called() before TypeDecl()";
} }
if (iter->second.ast != named_type) { if (iter->second.ast != named_type) {
diagnostics_.add_error("type with the name '" + diagnostics_.add_error("type with the name '" +

View File

@ -184,9 +184,9 @@ class Resolver {
size_t first_continue = kNoContinue; size_t first_continue = kNoContinue;
}; };
// Structure holding information for a NamedType // Structure holding information for a TypeDecl
struct NamedTypeInfo { struct TypeDeclInfo {
ast::NamedType const* const ast; ast::TypeDecl const* const ast;
sem::Type* const sem; sem::Type* const sem;
}; };
@ -270,7 +270,7 @@ class Resolver {
const std::string& rhs_type_name); const std::string& rhs_type_name);
bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor, bool ValidateVectorConstructor(const ast::TypeConstructorExpression* ctor,
const sem::Vector* vec_type); const sem::Vector* vec_type);
bool ValidateNamedType(const ast::NamedType* named_type) const; bool ValidateTypeDecl(const ast::TypeDecl* named_type) const;
/// @returns the sem::Type for the ast::Type `ty`, building it if it /// @returns the sem::Type for the ast::Type `ty`, building it if it
/// hasn't been constructed already. If an error is raised, nullptr is /// hasn't been constructed already. If an error is raised, nullptr is
@ -280,7 +280,7 @@ class Resolver {
/// @param named_type the named type to resolve /// @param named_type the named type to resolve
/// @returns the resolved semantic type /// @returns the resolved semantic type
sem::Type* NamedType(const ast::NamedType* named_type); sem::Type* TypeDecl(const ast::TypeDecl* named_type);
/// Builds and returns the semantic information for the array `arr`. /// Builds and returns the semantic information for the array `arr`.
/// This method does not mark the ast::Array node, nor attach the generated /// This method does not mark the ast::Array node, nor attach the generated
@ -397,7 +397,7 @@ class Resolver {
std::unordered_map<const ast::Variable*, VariableInfo*> variable_to_info_; std::unordered_map<const ast::Variable*, VariableInfo*> variable_to_info_;
std::unordered_map<ast::CallExpression*, FunctionCallInfo> function_calls_; std::unordered_map<ast::CallExpression*, FunctionCallInfo> function_calls_;
std::unordered_map<const ast::Expression*, ExpressionInfo> expr_info_; std::unordered_map<const ast::Expression*, ExpressionInfo> expr_info_;
std::unordered_map<Symbol, NamedTypeInfo> named_type_info_; std::unordered_map<Symbol, TypeDeclInfo> named_type_info_;
std::unordered_set<const ast::Node*> marked_; std::unordered_set<const ast::Node*> marked_;
std::unordered_map<uint32_t, const VariableInfo*> constant_ids_; std::unordered_map<uint32_t, const VariableInfo*> constant_ids_;

View File

@ -294,7 +294,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl) {
TEST_F(ResolverTest, Stmt_VariableDecl_Alias) { TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
auto* my_int = Alias("MyInt", ty.i32()); auto* my_int = Alias("MyInt", ty.i32());
auto* var = Var("my_var", my_int, ast::StorageClass::kNone, Expr(2)); auto* var = Var("my_var", ty.Of(my_int), ast::StorageClass::kNone, Expr(2));
auto* init = var->constructor(); auto* init = var->constructor();
auto* decl = Decl(var); auto* decl = Decl(var);
@ -449,7 +449,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Array) {
TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) { TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) {
auto* aary = Alias("myarrty", ty.array<f32, 3>()); auto* aary = Alias("myarrty", ty.array<f32, 3>());
Global("my_var", aary, ast::StorageClass::kPrivate); Global("my_var", ty.Of(aary), ast::StorageClass::kPrivate);
auto* acc = IndexAccessor("my_var", 2); auto* acc = IndexAccessor("my_var", 2);
WrapInFunction(acc); WrapInFunction(acc);
@ -813,12 +813,12 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput); auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput);
auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput); auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput);
auto* sb_var = auto* sb_var = Global("sb_var", ty.Of(s), ast::StorageClass::kStorage,
Global("sb_var", s, ast::StorageClass::kStorage, ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup); auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate); auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate);
@ -852,12 +852,12 @@ TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) {
auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput); auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput);
auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput); auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput);
auto* sb_var = auto* sb_var = Global("sb_var", ty.Of(s), ast::StorageClass::kStorage,
Global("sb_var", s, ast::StorageClass::kStorage, ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup); auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate); auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate);
@ -1097,7 +1097,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) {
TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
auto* st = Structure("S", {Member("first_member", ty.i32()), auto* st = Structure("S", {Member("first_member", ty.i32()),
Member("second_member", ty.f32())}); Member("second_member", ty.f32())});
Global("my_struct", st, ast::StorageClass::kInput); Global("my_struct", ty.Of(st), ast::StorageClass::kInput);
auto* mem = MemberAccessor("my_struct", "second_member"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -1120,8 +1120,8 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
auto* st = Structure("S", {Member("first_member", ty.i32()), auto* st = Structure("S", {Member("first_member", ty.i32()),
Member("second_member", ty.f32())}); Member("second_member", ty.f32())});
auto* alias = Alias("alias", st); auto* alias = Alias("alias", ty.Of(st));
Global("my_struct", alias, ast::StorageClass::kInput); Global("my_struct", ty.Of(alias), ast::StorageClass::kInput);
auto* mem = MemberAccessor("my_struct", "second_member"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -1200,8 +1200,8 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
// //
auto* stB = Structure("B", {Member("foo", ty.vec4<f32>())}); auto* stB = Structure("B", {Member("foo", ty.vec4<f32>())});
auto* stA = Structure("A", {Member("mem", ty.vec(stB, 3))}); auto* stA = Structure("A", {Member("mem", ty.vec(ty.Of(stB), 3))});
Global("c", stA, ast::StorageClass::kInput); Global("c", ty.Of(stA), ast::StorageClass::kInput);
auto* mem = MemberAccessor( auto* mem = MemberAccessor(
MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"), MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"),
@ -1220,7 +1220,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) { TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) {
auto* st = Structure("S", {Member("first_member", ty.f32()), auto* st = Structure("S", {Member("first_member", ty.f32()),
Member("second_member", ty.f32())}); Member("second_member", ty.f32())});
Global("my_struct", st, ast::StorageClass::kInput); Global("my_struct", ty.Of(st), ast::StorageClass::kInput);
auto* expr = Add(MemberAccessor("my_struct", "first_member"), auto* expr = Add(MemberAccessor("my_struct", "first_member"),
MemberAccessor("my_struct", "second_member")); MemberAccessor("my_struct", "second_member"));
@ -1819,11 +1819,12 @@ TEST_F(ResolverTest, Access_SetForStorageBuffer) {
// var<storage> g : S; // var<storage> g : S;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* var = Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage, auto* var =
ast::DecorationList{ Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -68,7 +68,7 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) {
TEST_F(ResolverStorageClassValidationTest, StorageBufferArray) { TEST_F(ResolverStorageClassValidationTest, StorageBufferArray) {
// var<storage, read> g : array<S, 3>; // var<storage, read> g : array<S, 3>;
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = ty.array(s, 3); auto* a = ty.array(ty.Of(s), 3);
Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
@ -87,7 +87,7 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferBoolAlias) {
// type a = bool; // type a = bool;
// var<storage, read> g : a; // var<storage, read> g : a;
auto* a = Alias("a", ty.bool_()); auto* a = Alias("a", ty.bool_());
Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kStorage,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -104,7 +104,7 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoBlockDecoration) {
// struct S { x : i32 }; // struct S { x : i32 };
// var<storage, read> g : S; // var<storage, read> g : S;
auto* s = Structure(Source{{12, 34}}, "S", {Member("x", ty.i32())}); auto* s = Structure(Source{{12, 34}}, "S", {Member("x", ty.i32())});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -124,7 +124,7 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Basic) {
// var<storage, read> g : S; // var<storage, read> g : S;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -140,9 +140,9 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Aliases) {
// var<storage, read> g : a1; // var<storage, read> g : a1;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* a1 = Alias("a1", s); auto* a1 = Alias("a1", ty.Of(s));
auto* a2 = Alias("a2", a1); auto* a2 = Alias("a2", ty.Of(a1));
Global(Source{{56, 78}}, "g", a2, ast::StorageClass::kStorage, Global(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage,
ast::Access::kRead, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -188,7 +188,7 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) {
TEST_F(ResolverStorageClassValidationTest, UniformBufferArray) { TEST_F(ResolverStorageClassValidationTest, UniformBufferArray) {
// var<uniform> g : array<S, 3>; // var<uniform> g : array<S, 3>;
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = ty.array(s, 3); auto* a = ty.array(ty.Of(s), 3);
Global(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform, Global(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -206,7 +206,7 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferBoolAlias) {
// type a = bool; // type a = bool;
// var<uniform> g : a; // var<uniform> g : a;
auto* a = Alias("a", ty.bool_()); auto* a = Alias("a", ty.bool_());
Global(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform, Global(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -223,7 +223,7 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferNoBlockDecoration) {
// struct S { x : i32 }; // struct S { x : i32 };
// var<uniform> g : S; // var<uniform> g : S;
auto* s = Structure(Source{{12, 34}}, "S", {Member("x", ty.i32())}); auto* s = Structure(Source{{12, 34}}, "S", {Member("x", ty.i32())});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kUniform, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -242,7 +242,7 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferNoError_Basic) {
// var<uniform> g : S; // var<uniform> g : S;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kUniform, Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -257,8 +257,8 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferNoError_Aliases) {
// var<uniform> g : a1; // var<uniform> g : a1;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())}, auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* a1 = Alias("a1", s); auto* a1 = Alias("a1", ty.Of(s));
Global(Source{{56, 78}}, "g", a1, ast::StorageClass::kUniform, Global(Source{{56, 78}}, "g", ty.Of(a1), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -56,8 +56,8 @@ TEST_F(ResolverStructLayoutTest, Alias) {
auto* alias_b = Alias("b", ty.f32()); auto* alias_b = Alias("b", ty.f32());
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", alias_a), Member("a", ty.Of(alias_a)),
Member("b", alias_b), Member("b", ty.Of(alias_b)),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -195,8 +195,8 @@ TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayOfStructure) {
Member("a", ty.vec2<i32>()), Member("a", ty.vec2<i32>()),
Member("b", ty.vec3<i32>()), Member("b", ty.vec3<i32>()),
Member("c", ty.vec4<i32>()), Member("c", ty.vec4<i32>()),
}); // size: 48 }); // size: 48
auto* outer = ty.array(inner, 12); // size: 12 * 48 auto* outer = ty.array(ty.Of(inner), 12); // size: 12 * 48
auto* s = Structure("S", { auto* s = Structure("S", {
Member("c", outer), Member("c", outer),
}); });
@ -296,7 +296,7 @@ TEST_F(ResolverStructLayoutTest, NestedStruct) {
}); });
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", inner), Member("b", ty.Of(inner)),
Member("c", ty.i32()), Member("c", ty.i32()),
}); });
@ -328,7 +328,7 @@ TEST_F(ResolverStructLayoutTest, SizeDecorations) {
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.f32(), {MemberSize(4)}), Member("a", ty.f32(), {MemberSize(4)}),
Member("b", ty.u32(), {MemberSize(8)}), Member("b", ty.u32(), {MemberSize(8)}),
Member("c", inner), Member("c", ty.Of(inner)),
Member("d", ty.i32(), {MemberSize(32)}), Member("d", ty.i32(), {MemberSize(32)}),
}); });
@ -363,7 +363,7 @@ TEST_F(ResolverStructLayoutTest, AlignDecorations) {
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.f32(), {MemberAlign(4)}), Member("a", ty.f32(), {MemberAlign(4)}),
Member("b", ty.u32(), {MemberAlign(8)}), Member("b", ty.u32(), {MemberAlign(8)}),
Member("c", inner), Member("c", ty.Of(inner)),
Member("d", ty.i32(), {MemberAlign(32)}), Member("d", ty.i32(), {MemberAlign(32)}),
}); });

View File

@ -40,7 +40,7 @@ TEST_F(ResolverPipelineStageUseTest, UnusedStruct) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointParam) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointParam) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
Func("foo", {Param("param", s)}, ty.void_(), {}, {}); Func("foo", {Param("param", ty.Of(s))}, ty.void_(), {}, {});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -52,7 +52,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointParam) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
Func("foo", {}, s, {Return(Construct(s, Expr(0.f)))}, {}); Func("foo", {}, ty.Of(s), {Return(Construct(ty.Of(s), Expr(0.f)))}, {});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -64,7 +64,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
Func("main", {Param("param", s)}, ty.vec4<f32>(), Func("main", {Param("param", ty.Of(s))}, ty.vec4<f32>(),
{Return(Construct(ty.vec4<f32>()))}, {Return(Construct(ty.vec4<f32>()))},
{Stage(ast::PipelineStage::kVertex)}, {Stage(ast::PipelineStage::kVertex)},
{Builtin(ast::Builtin::kPosition)}); {Builtin(ast::Builtin::kPosition)});
@ -81,7 +81,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderReturnType) {
auto* s = Structure( auto* s = Structure(
"S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})}); "S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})});
Func("main", {}, s, {Return(Construct(s, Expr(0.f)))}, Func("main", {}, ty.Of(s), {Return(Construct(ty.Of(s), Expr(0.f)))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -95,7 +95,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderReturnType) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderParam) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderParam) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
Func("main", {Param("param", s)}, ty.void_(), {}, Func("main", {Param("param", ty.Of(s))}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -109,7 +109,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderParam) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderReturnType) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsFragmentShaderReturnType) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
Func("main", {}, s, {Return(Construct(s, Expr(0.f)))}, Func("main", {}, ty.Of(s), {Return(Construct(ty.Of(s), Expr(0.f)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -125,7 +125,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsComputeShaderParam) {
"S", "S",
{Member("a", ty.u32(), {Builtin(ast::Builtin::kLocalInvocationIndex)})}); {Member("a", ty.u32(), {Builtin(ast::Builtin::kLocalInvocationIndex)})});
Func("main", {Param("param", s)}, ty.void_(), {}, Func("main", {Param("param", ty.Of(s))}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute)}); {Stage(ast::PipelineStage::kCompute)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -140,10 +140,11 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedMultipleStages) {
auto* s = Structure( auto* s = Structure(
"S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})}); "S", {Member("a", ty.f32(), {Builtin(ast::Builtin::kPosition)})});
Func("vert_main", {Param("param", s)}, s, {Return(Construct(s, Expr(0.f)))}, Func("vert_main", {Param("param", ty.Of(s))}, ty.Of(s),
{Return(Construct(ty.Of(s), Expr(0.f)))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("frag_main", {Param("param", s)}, ty.void_(), {}, Func("frag_main", {Param("param", ty.Of(s))}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -158,9 +159,9 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedMultipleStages) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
auto* s_alias = Alias("S_alias", s); auto* s_alias = Alias("S_alias", ty.Of(s));
Func("main", {Param("param", s_alias)}, ty.void_(), {}, Func("main", {Param("param", ty.Of(s_alias))}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -173,9 +174,10 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) { TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})}); auto* s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
auto* s_alias = Alias("S_alias", s); auto* s_alias = Alias("S_alias", ty.Of(s));
Func("main", {}, s_alias, {Return(Construct(s_alias, Expr(0.f)))}, Func("main", {}, ty.Of(s_alias),
{Return(Construct(ty.Of(s_alias), Expr(0.f)))},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -40,7 +40,7 @@ TEST_F(ResolverStorageClassUseTest, UnreachableStruct) {
TEST_F(ResolverStorageClassUseTest, StructReachableFromParameter) { TEST_F(ResolverStorageClassUseTest, StructReachableFromParameter) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
Func("f", {Param("param", s)}, ty.void_(), {}, {}); Func("f", {Param("param", ty.Of(s))}, ty.void_(), {}, {});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -53,7 +53,7 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromParameter) {
TEST_F(ResolverStorageClassUseTest, StructReachableFromReturnType) { TEST_F(ResolverStorageClassUseTest, StructReachableFromReturnType) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
Func("f", {}, s, {Return(Construct(s))}, {}); Func("f", {}, ty.Of(s), {Return(Construct(ty.Of(s)))}, {});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -66,7 +66,7 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromReturnType) {
TEST_F(ResolverStorageClassUseTest, StructReachableFromGlobal) { TEST_F(ResolverStorageClassUseTest, StructReachableFromGlobal) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -78,8 +78,8 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromGlobal) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalAlias) { TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalAlias) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = Alias("A", s); auto* a = Alias("A", ty.Of(s));
Global("g", a, ast::StorageClass::kPrivate); Global("g", ty.Of(a), ast::StorageClass::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -91,8 +91,8 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalAlias) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalStruct) { TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalStruct) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* o = Structure("O", {Member("a", s)}); auto* o = Structure("O", {Member("a", ty.Of(s))});
Global("g", o, ast::StorageClass::kPrivate); Global("g", ty.Of(o), ast::StorageClass::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -104,7 +104,7 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalStruct) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalArray) { TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalArray) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = ty.array(s, 3); auto* a = ty.array(ty.Of(s), 3);
Global("g", a, ast::StorageClass::kPrivate); Global("g", a, ast::StorageClass::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -118,7 +118,7 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalArray) {
TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) { TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
WrapInFunction(Var("g", s)); WrapInFunction(Var("g", ty.Of(s)));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -130,8 +130,8 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) { TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = Alias("A", s); auto* a = Alias("A", ty.Of(s));
WrapInFunction(Var("g", a)); WrapInFunction(Var("g", ty.Of(a)));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -143,8 +143,8 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) { TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* o = Structure("O", {Member("a", s)}); auto* o = Structure("O", {Member("a", ty.Of(s))});
WrapInFunction(Var("g", o)); WrapInFunction(Var("g", ty.Of(o)));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -156,7 +156,7 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) {
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) { TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) {
auto* s = Structure("S", {Member("a", ty.f32())}); auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = ty.array(s, 3); auto* a = ty.array(ty.Of(s), 3);
WrapInFunction(Var("g", a)); WrapInFunction(Var("g", a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -170,17 +170,17 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) {
TEST_F(ResolverStorageClassUseTest, StructMultipleStorageClassUses) { TEST_F(ResolverStorageClassUseTest, StructMultipleStorageClassUses) {
auto* s = Structure("S", {Member("a", ty.f32())}, auto* s = Structure("S", {Member("a", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("x", s, ast::StorageClass::kUniform, Global("x", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
Global("y", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("y", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
WrapInFunction(Var("g", s)); WrapInFunction(Var("g", ty.Of(s)));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -341,7 +341,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) {
auto* alias = Alias("RTArr", ty.array<u32>()); auto* alias = Alias("RTArr", ty.array<u32>());
Structure("s", Structure("s",
{ {
Member(Source{{12, 34}}, "b", alias), Member(Source{{12, 34}}, "b", ty.Of(alias)),
Member("a", ty.u32()), Member("a", ty.u32()),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
@ -367,7 +367,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) {
Structure("s", Structure("s",
{ {
Member("a", ty.u32()), Member("a", ty.u32()),
Member("b", alias), Member("b", ty.Of(alias)),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});

View File

@ -1709,7 +1709,7 @@ TEST_F(ResolverValidationTest,
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) { TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
auto* alias = Alias("UnsignedInt", ty.u32()); auto* alias = Alias("UnsignedInt", ty.u32());
Global("uint_var", alias, ast::StorageClass::kInput); Global("uint_var", ty.Of(alias), ast::StorageClass::kInput);
auto* tc = vec2<f32>(Expr(Source{{12, 34}}, "uint_var")); auto* tc = vec2<f32>(Expr(Source{{12, 34}}, "uint_var"));
WrapInFunction(tc); WrapInFunction(tc);
@ -1723,8 +1723,8 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) { TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
auto* vec2_alias = Alias("VectorFloat2", ty.vec2<f32>()); auto* vec2_alias = Alias("VectorFloat2", ty.vec2<f32>());
Global("my_f32", f32_alias, ast::StorageClass::kInput); Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kInput);
Global("my_vec2", vec2_alias, ast::StorageClass::kInput); Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kInput);
auto* tc = vec3<f32>("my_vec2", "my_f32"); auto* tc = vec3<f32>("my_vec2", "my_f32");
WrapInFunction(tc); WrapInFunction(tc);
@ -1735,7 +1735,7 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_ElementTypeAlias_Error) {
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
// vec2<Float32>(1.0f, 1u) // vec2<Float32>(1.0f, 1u)
auto* vec_type = ty.vec(f32_alias, 2); auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
auto* tc = create<ast::TypeConstructorExpression>( auto* tc = create<ast::TypeConstructorExpression>(
Source{{12, 34}}, vec_type, Source{{12, 34}}, vec_type,
ExprList(1.0f, create<ast::ScalarConstructorExpression>(Source{{12, 40}}, ExprList(1.0f, create<ast::ScalarConstructorExpression>(Source{{12, 40}},
@ -1753,7 +1753,7 @@ TEST_F(ResolverValidationTest,
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
// vec2<Float32>(1.0f, 1.0f) // vec2<Float32>(1.0f, 1.0f)
auto* vec_type = ty.vec(f32_alias, 2); auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, vec_type, auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, vec_type,
ExprList(1.0f, 1.0f)); ExprList(1.0f, 1.0f));
WrapInFunction(tc); WrapInFunction(tc);
@ -1766,7 +1766,7 @@ TEST_F(ResolverValidationTest,
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
// vec3<u32>(vec<Float32>(), 1.0f) // vec3<u32>(vec<Float32>(), 1.0f)
auto* vec_type = ty.vec(f32_alias, 2); auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
auto* tc = vec3<u32>(create<ast::TypeConstructorExpression>( auto* tc = vec3<u32>(create<ast::TypeConstructorExpression>(
Source{{12, 34}}, vec_type, ExprList()), Source{{12, 34}}, vec_type, ExprList()),
1.0f); 1.0f);
@ -1783,7 +1783,7 @@ TEST_F(ResolverValidationTest,
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
// vec3<f32>(vec<Float32>(), 1.0f) // vec3<f32>(vec<Float32>(), 1.0f)
auto* vec_type = ty.vec(f32_alias, 2); auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>( auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
Source{{12, 34}}, vec_type, ExprList()), Source{{12, 34}}, vec_type, ExprList()),
1.0f); 1.0f);
@ -2019,7 +2019,7 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) {
Source{{12, i}}, vec_type, ExprList())); Source{{12, i}}, vec_type, ExprList()));
} }
auto* matrix_type = ty.mat(f32_alias, param.columns, param.rows); auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows);
auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type, auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
std::move(args)); std::move(args));
WrapInFunction(tc); WrapInFunction(tc);
@ -2044,7 +2044,7 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) {
Source{{12, i}}, vec_type, ExprList())); Source{{12, i}}, vec_type, ExprList()));
} }
auto* matrix_type = ty.mat(f32_alias, param.columns, param.rows); auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows);
auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type, auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
std::move(args)); std::move(args));
WrapInFunction(tc); WrapInFunction(tc);
@ -2054,10 +2054,9 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) {
TEST_F(ResolverValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) { TEST_F(ResolverValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) {
auto* alias = Alias("VectorUnsigned2", ty.vec2<u32>()); auto* alias = Alias("VectorUnsigned2", ty.vec2<u32>());
auto* tc = mat2x2<f32>( auto* tc = mat2x2<f32>(create<ast::TypeConstructorExpression>(
create<ast::TypeConstructorExpression>( Source{{12, 34}}, ty.Of(alias), ExprList()),
Source{{12, 34}}, ty.MaybeCreateTypename(alias), ExprList()), vec2<f32>());
vec2<f32>());
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -2075,7 +2074,7 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentTypeAlias_Success) {
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
args.push_back(create<ast::TypeConstructorExpression>( args.push_back(create<ast::TypeConstructorExpression>(
Source{{12, i}}, ty.MaybeCreateTypename(vec_alias), ExprList())); Source{{12, i}}, ty.Of(vec_alias), ExprList()));
} }
auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type, auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
@ -2092,7 +2091,7 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Error) {
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
auto* vec_type = ty.vec(f32_alias, param.rows); auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows);
args.push_back(create<ast::TypeConstructorExpression>( args.push_back(create<ast::TypeConstructorExpression>(
Source{{12, i}}, vec_type, ExprList())); Source{{12, i}}, vec_type, ExprList()));
} }
@ -2115,7 +2114,7 @@ TEST_P(MatrixConstructorTest,
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
auto* vec_type = ty.vec(f32_alias, param.rows); auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows);
args.push_back(create<ast::TypeConstructorExpression>( args.push_back(create<ast::TypeConstructorExpression>(
Source{{12, i}}, vec_type, ExprList())); Source{{12, i}}, vec_type, ExprList()));
} }

View File

@ -39,14 +39,14 @@ TEST_F(ResolverVarLetTest, TypeOfVar) {
// } // }
auto* S = Structure("S", {Member("i", ty.i32())}); auto* S = Structure("S", {Member("i", ty.i32())});
auto* A = Alias("A", S); auto* A = Alias("A", ty.Of(S));
auto* i = Var("i", ty.i32(), ast::StorageClass::kNone); auto* i = Var("i", ty.i32(), ast::StorageClass::kNone);
auto* u = Var("u", ty.u32(), ast::StorageClass::kNone); auto* u = Var("u", ty.u32(), ast::StorageClass::kNone);
auto* f = Var("f", ty.f32(), ast::StorageClass::kNone); auto* f = Var("f", ty.f32(), ast::StorageClass::kNone);
auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone); auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone);
auto* s = Var("s", S, ast::StorageClass::kNone); auto* s = Var("s", ty.Of(S), ast::StorageClass::kNone);
auto* a = Var("a", A, ast::StorageClass::kNone); auto* a = Var("a", ty.Of(A), ast::StorageClass::kNone);
Func("F", {}, ty.void_(), Func("F", {}, ty.void_(),
{ {
@ -90,15 +90,15 @@ TEST_F(ResolverVarLetTest, TypeOfLet) {
// } // }
auto* S = Structure("S", {Member("i", ty.i32())}); auto* S = Structure("S", {Member("i", ty.i32())});
auto* A = Alias("A", S); auto* A = Alias("A", ty.Of(S));
auto* v = Var("v", ty.i32(), ast::StorageClass::kNone); auto* v = Var("v", ty.i32(), ast::StorageClass::kNone);
auto* i = Const("i", ty.i32(), Expr(1)); auto* i = Const("i", ty.i32(), Expr(1));
auto* u = Const("u", ty.u32(), Expr(1u)); auto* u = Const("u", ty.u32(), Expr(1u));
auto* f = Const("f", ty.f32(), Expr(1.f)); auto* f = Const("f", ty.f32(), Expr(1.f));
auto* b = Const("b", ty.bool_(), Expr(true)); auto* b = Const("b", ty.bool_(), Expr(true));
auto* s = Const("s", S, Construct(S, Expr(1))); auto* s = Const("s", ty.Of(S), Construct(ty.Of(S), Expr(1)));
auto* a = Const("a", A, Construct(A, Expr(1))); auto* a = Const("a", ty.Of(A), Construct(ty.Of(A), Expr(1)));
auto* p = auto* p =
Const("p", ty.pointer<i32>(ast::StorageClass::kFunction), AddressOf(v)); Const("p", ty.pointer<i32>(ast::StorageClass::kFunction), AddressOf(v));
@ -135,12 +135,12 @@ TEST_F(ResolverVarLetTest, DefaultVarStorageClass) {
auto* function = Var("f", ty.i32()); auto* function = Var("f", ty.i32());
auto* private_ = Global("p", ty.i32(), ast::StorageClass::kPrivate); auto* private_ = Global("p", ty.i32(), ast::StorageClass::kPrivate);
auto* workgroup = Global("w", ty.i32(), ast::StorageClass::kWorkgroup); auto* workgroup = Global("w", ty.i32(), ast::StorageClass::kWorkgroup);
auto* uniform = Global("ub", buf, ast::StorageClass::kUniform, auto* uniform = Global("ub", ty.Of(buf), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* storage = Global("sb", buf, ast::StorageClass::kStorage, auto* storage = Global("sb", ty.Of(buf), ast::StorageClass::kStorage,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -180,12 +180,12 @@ TEST_F(ResolverVarLetTest, ExplicitVarStorageClass) {
auto* buf = Structure("S", {Member("m", ty.i32())}, auto* buf = Structure("S", {Member("m", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* storage = auto* storage = Global("sb", ty.Of(buf), ast::StorageClass::kStorage,
Global("sb", buf, ast::StorageClass::kStorage, ast::Access::kReadWrite, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -207,14 +207,14 @@ TEST_F(ResolverVarLetTest, LetInheritsAccessFromOriginatingVariable) {
// let p = &s.inner.arr[2]; // let p = &s.inner.arr[2];
// } // }
auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())}); auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", {Member("inner", inner)}, auto* buf = Structure("S", {Member("inner", ty.Of(inner))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* storage = auto* storage = Global("s", ty.Of(buf), ast::StorageClass::kStorage,
Global("s", buf, ast::StorageClass::kStorage, ast::Access::kReadWrite, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
}); });
auto* expr = auto* expr =
IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4); IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 4);

View File

@ -81,7 +81,7 @@ TEST_F(ResolverVarLetValidationTest, VarConstructorWrongType) {
TEST_F(ResolverVarLetValidationTest, LetConstructorWrongTypeViaAlias) { TEST_F(ResolverVarLetValidationTest, LetConstructorWrongTypeViaAlias) {
auto* a = Alias("I32", ty.i32()); auto* a = Alias("I32", ty.i32());
WrapInFunction(Const(Source{{3, 3}}, "v", a, Expr(2u))); WrapInFunction(Const(Source{{3, 3}}, "v", ty.Of(a), Expr(2u)));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
@ -92,7 +92,7 @@ TEST_F(ResolverVarLetValidationTest, LetConstructorWrongTypeViaAlias) {
TEST_F(ResolverVarLetValidationTest, VarConstructorWrongTypeViaAlias) { TEST_F(ResolverVarLetValidationTest, VarConstructorWrongTypeViaAlias) {
auto* a = Alias("I32", ty.i32()); auto* a = Alias("I32", ty.i32());
WrapInFunction( WrapInFunction(
Var(Source{{3, 3}}, "v", a, ast::StorageClass::kNone, Expr(2u))); Var(Source{{3, 3}}, "v", ty.Of(a), ast::StorageClass::kNone, Expr(2u)));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
@ -228,9 +228,9 @@ TEST_F(ResolverVarLetValidationTest, InferredPtrStorageAccessMismatch) {
// let p : pointer<storage, i32, read_write> = &s.inner.arr[2]; // let p : pointer<storage, i32, read_write> = &s.inner.arr[2];
// } // }
auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())}); auto* inner = Structure("Inner", {Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", {Member("inner", inner)}, auto* buf = Structure("S", {Member("inner", ty.Of(inner))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* storage = Global("s", buf, ast::StorageClass::kStorage, auto* storage = Global("s", ty.Of(buf), ast::StorageClass::kStorage,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -13,11 +13,13 @@
// limitations under the License. // limitations under the License.
#include "src/sem/struct.h" #include "src/sem/struct.h"
#include "src/ast/struct_member.h"
#include <string> #include <string>
#include <utility> #include <utility>
#include "src/ast/struct_member.h"
#include "src/symbol_table.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct); TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct);
TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember); TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember);
@ -51,7 +53,7 @@ std::string Struct::type_name() const {
} }
std::string Struct::FriendlyName(const SymbolTable& symbols) const { std::string Struct::FriendlyName(const SymbolTable& symbols) const {
return declaration_->FriendlyName(symbols); return symbols.NameFor(declaration_->name());
} }
StructMember::StructMember(ast::StructMember* declaration, StructMember::StructMember(ast::StructMember* declaration,

View File

@ -28,6 +28,7 @@ class MemberAccessorExpression;
class Statement; class Statement;
class StructMember; class StructMember;
class Type; class Type;
class TypeDecl;
class Variable; class Variable;
} // namespace ast } // namespace ast
@ -57,6 +58,7 @@ struct TypeMappings {
Statement* operator()(ast::Statement*); Statement* operator()(ast::Statement*);
StructMember* operator()(ast::StructMember*); StructMember* operator()(ast::StructMember*);
Type* operator()(ast::Type*); Type* operator()(ast::Type*);
Type* operator()(ast::TypeDecl*);
Variable* operator()(ast::Variable*); Variable* operator()(ast::Variable*);
//! @endcond //! @endcond
}; };

View File

@ -332,7 +332,7 @@ void InsertGlobal(CloneContext& ctx,
} }
/// @returns the unwrapped, user-declared constructed type of ty. /// @returns the unwrapped, user-declared constructed type of ty.
const ast::NamedType* ConstructedTypeOf(const sem::Type* ty) { const ast::TypeDecl* ConstructedTypeOf(const sem::Type* ty) {
while (true) { while (true) {
if (auto* ref = ty->As<sem::Reference>()) { if (auto* ref = ty->As<sem::Reference>()) {
ty = ref->StoreType(); ty = ref->StoreType();
@ -414,7 +414,7 @@ struct DecomposeStorageAccess::State {
/// @param var_user the variable user /// @param var_user the variable user
/// @return the name of the function that performs the load /// @return the name of the function that performs the load
Symbol LoadFunc(CloneContext& ctx, Symbol LoadFunc(CloneContext& ctx,
const ast::NamedType* insert_after, const ast::TypeDecl* insert_after,
const sem::Type* buf_ty, const sem::Type* buf_ty,
const sem::Type* el_ty, const sem::Type* el_ty,
const sem::VariableUser* var_user) { const sem::VariableUser* var_user) {
@ -490,7 +490,7 @@ struct DecomposeStorageAccess::State {
/// @param var_user the variable user /// @param var_user the variable user
/// @return the name of the function that performs the store /// @return the name of the function that performs the store
Symbol StoreFunc(CloneContext& ctx, Symbol StoreFunc(CloneContext& ctx,
const ast::NamedType* insert_after, const ast::TypeDecl* insert_after,
const sem::Type* buf_ty, const sem::Type* buf_ty,
const sem::Type* el_ty, const sem::Type* el_ty,
const sem::VariableUser* var_user) { const sem::VariableUser* var_user) {

View File

@ -133,14 +133,14 @@ Output FirstIndexOffset::Run(const Program* in, const DataMap& data) {
instance_index_offset = offset; instance_index_offset = offset;
offset += 4; offset += 4;
} }
auto* struct_type = auto* struct_ =
ctx.dst->Structure(ctx.dst->Sym(), std::move(members), ctx.dst->Structure(ctx.dst->Sym(), std::move(members),
{ctx.dst->create<ast::StructBlockDecoration>()}); {ctx.dst->create<ast::StructBlockDecoration>()});
// Create a global to hold the uniform buffer // Create a global to hold the uniform buffer
Symbol buffer_name = ctx.dst->Sym(); Symbol buffer_name = ctx.dst->Sym();
ctx.dst->Global(buffer_name, struct_type, ast::StorageClass::kUniform, ctx.dst->Global(buffer_name, ctx.dst->ty.Of(struct_),
nullptr, ast::StorageClass::kUniform, nullptr,
ast::DecorationList{ ast::DecorationList{
ctx.dst->create<ast::BindingDecoration>(ub_binding), ctx.dst->create<ast::BindingDecoration>(ub_binding),
ctx.dst->create<ast::GroupDecoration>(ub_group), ctx.dst->create<ast::GroupDecoration>(ub_group),

View File

@ -69,7 +69,7 @@ Output SingleEntryPoint::Run(const Program* in, const DataMap& data) {
// Clone any module-scope variables, types, and functions that are statically // Clone any module-scope variables, types, and functions that are statically
// referenced by the target entry point. // referenced by the target entry point.
for (auto* decl : in->AST().GlobalDeclarations()) { for (auto* decl : in->AST().GlobalDeclarations()) {
if (auto* ty = decl->As<ast::NamedType>()) { if (auto* ty = decl->As<ast::TypeDecl>()) {
// TODO(jrprice): Strip unused types. // TODO(jrprice): Strip unused types.
out.AST().AddConstructedType(ctx.Clone(ty)); out.AST().AddConstructedType(ctx.Clone(ty));
} else if (auto* var = decl->As<ast::Variable>()) { } else if (auto* var = decl->As<ast::Variable>()) {

View File

@ -216,8 +216,8 @@ struct State {
for (uint32_t i = 0; i < cfg.vertex_state.size(); ++i) { for (uint32_t i = 0; i < cfg.vertex_state.size(); ++i) {
// The decorated variable with struct type // The decorated variable with struct type
ctx.dst->Global( ctx.dst->Global(
GetVertexBufferName(i), struct_type, ast::StorageClass::kStorage, GetVertexBufferName(i), ctx.dst->ty.Of(struct_type),
ast::Access::kRead, ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
ctx.dst->create<ast::BindingDecoration>(i), ctx.dst->create<ast::BindingDecoration>(i),
ctx.dst->create<ast::GroupDecoration>(cfg.pulling_group), ctx.dst->create<ast::GroupDecoration>(cfg.pulling_group),
@ -485,7 +485,8 @@ struct State {
auto* new_struct = ctx.dst->Structure(ctx.dst->Sym(), new_members); auto* new_struct = ctx.dst->Structure(ctx.dst->Sym(), new_members);
// Create a new function parameter with this struct. // Create a new function parameter with this struct.
auto* new_param = ctx.dst->Param(ctx.dst->Sym(), new_struct); auto* new_param =
ctx.dst->Param(ctx.dst->Sym(), ctx.dst->ty.Of(new_struct));
new_function_parameters.push_back(new_param); new_function_parameters.push_back(new_param);
// Copy values from the new parameter to the function-scope variable. // Copy values from the new parameter to the function-scope variable.

View File

@ -392,6 +392,12 @@ class GeneratorImpl : public TextGenerator {
return builder_.TypeOf(type); return builder_.TypeOf(type);
} }
/// @returns the resolved type of the ast::TypeDecl `type_decl`
/// @param type_decl the type
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const {
return builder_.TypeOf(type_decl);
}
/// Emits `prefix`, followed by an opening brace `{`, then calls `cb` to emit /// Emits `prefix`, followed by an opening brace `{`, then calls `cb` to emit
/// the block body, then finally emits the closing brace `}`. /// the block body, then finally emits the closing brace `}`.
/// @param out the output stream /// @param out the output stream

View File

@ -201,7 +201,7 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Struct) {
Member("c", ty.vec3<i32>()), Member("c", ty.vec3<i32>()),
}); });
WrapInFunction(Construct(str, 1, 2.0f, vec3<i32>(3, 4, 5))); WrapInFunction(Construct(ty.Of(str), 1, 2.0f, vec3<i32>(3, 4, 5)));
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();
@ -218,7 +218,7 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Struct_Empty) {
Member("c", ty.vec3<i32>()), Member("c", ty.vec3<i32>()),
}); });
WrapInFunction(Construct(str)); WrapInFunction(Construct(ty.Of(str)));
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();

View File

@ -205,12 +205,12 @@ TEST_F(HlslGeneratorImplTest_Function,
Member("col2", ty.f32(), {Location(2)}), Member("col2", ty.f32(), {Location(2)}),
}); });
Func("vert_main", {}, interface_struct, Func("vert_main", {}, ty.Of(interface_struct),
{Return(Construct(interface_struct, Construct(ty.vec4<f32>()), {Return(Construct(ty.Of(interface_struct), Construct(ty.vec4<f32>()),
Expr(0.5f), Expr(0.25f)))}, Expr(0.5f), Expr(0.25f)))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("frag_main", {Param("inputs", interface_struct)}, ty.void_(), Func("frag_main", {Param("inputs", ty.Of(interface_struct))}, ty.void_(),
{ {
Decl(Const("r", ty.f32(), MemberAccessor("inputs", "col1"))), Decl(Const("r", ty.f32(), MemberAccessor("inputs", "col1"))),
Decl(Const("g", ty.f32(), MemberAccessor("inputs", "col2"))), Decl(Const("g", ty.f32(), MemberAccessor("inputs", "col2"))),
@ -274,19 +274,20 @@ TEST_F(HlslGeneratorImplTest_Function,
"VertexOutput", "VertexOutput",
{Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)})}); {Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)})});
Func("foo", {Param("x", ty.f32())}, vertex_output_struct, Func("foo", {Param("x", ty.f32())}, ty.Of(vertex_output_struct),
{Return(Construct(vertex_output_struct, {Return(Construct(ty.Of(vertex_output_struct),
Construct(ty.vec4<f32>(), "x", "x", "x", Expr(1.f))))}, Construct(ty.vec4<f32>(), "x", "x", "x", Expr(1.f))))},
{}); {});
Func("vert_main1", {}, vertex_output_struct, Func("vert_main1", {}, ty.Of(vertex_output_struct),
{Return(Construct(vertex_output_struct, Expr(Call("foo", Expr(0.5f)))))}, {Return(Construct(ty.Of(vertex_output_struct),
Expr(Call("foo", Expr(0.5f)))))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func( Func("vert_main2", {}, ty.Of(vertex_output_struct),
"vert_main2", {}, vertex_output_struct, {Return(Construct(ty.Of(vertex_output_struct),
{Return(Construct(vertex_output_struct, Expr(Call("foo", Expr(0.25f)))))}, Expr(Call("foo", Expr(0.25f)))))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();
@ -327,7 +328,7 @@ TEST_F(HlslGeneratorImplTest_Function,
Emit_Decoration_EntryPoint_With_Uniform) { Emit_Decoration_EntryPoint_With_Uniform) {
auto* ubo_ty = Structure("UBO", {Member("coord", ty.vec4<f32>())}, auto* ubo_ty = Structure("UBO", {Member("coord", ty.vec4<f32>())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* ubo = Global("ubo", ubo_ty, ast::StorageClass::kUniform, auto* ubo = Global("ubo", ty.Of(ubo_ty), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -382,7 +383,7 @@ TEST_F(HlslGeneratorImplTest_Function,
auto* s = Structure("Uniforms", {Member("coord", ty.vec4<f32>())}, auto* s = Structure("Uniforms", {Member("coord", ty.vec4<f32>())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("uniforms", s, ast::StorageClass::kUniform, Global("uniforms", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -428,7 +429,8 @@ TEST_F(HlslGeneratorImplTest_Function,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -472,7 +474,7 @@ TEST_F(HlslGeneratorImplTest_Function,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("coord", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -516,7 +518,7 @@ TEST_F(HlslGeneratorImplTest_Function,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -557,7 +559,8 @@ TEST_F(HlslGeneratorImplTest_Function,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -756,7 +759,7 @@ TEST_F(HlslGeneratorImplTest_Function,
Emit_Decoration_Called_By_EntryPoint_With_Uniform) { Emit_Decoration_Called_By_EntryPoint_With_Uniform) {
auto* s = Structure("S", {Member("x", ty.f32())}, auto* s = Structure("S", {Member("x", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kUniform, Global("coord", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -806,7 +809,8 @@ TEST_F(HlslGeneratorImplTest_Function,
Emit_Decoration_Called_By_EntryPoint_With_StorageBuffer) { Emit_Decoration_Called_By_EntryPoint_With_StorageBuffer) {
auto* s = Structure("S", {Member("x", ty.f32())}, auto* s = Structure("S", {Member("x", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -1055,7 +1059,7 @@ TEST_F(HlslGeneratorImplTest_Function,
auto* s = Structure("Data", {Member("d", ty.f32())}, auto* s = Structure("Data", {Member("d", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("data", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("data", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -98,7 +98,8 @@ class HlslGeneratorImplTest_MemberAccessorBase : public BASE {
auto* s = auto* s =
b.Structure("Data", members, {b.create<ast::StructBlockDecoration>()}); b.Structure("Data", members, {b.create<ast::StructBlockDecoration>()});
b.Global("data", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, b.Global("data", b.ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
b.create<ast::BindingDecoration>(0), b.create<ast::BindingDecoration>(0),
b.create<ast::GroupDecoration>(1), b.create<ast::GroupDecoration>(1),
@ -123,7 +124,7 @@ using HlslGeneratorImplTest_MemberAccessorWithParam =
TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor) { TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor) {
auto* s = Structure("Data", {Member("mem", ty.f32())}); auto* s = Structure("Data", {Member("mem", ty.f32())});
Global("str", s, ast::StorageClass::kPrivate); Global("str", ty.Of(s), ast::StorageClass::kPrivate);
auto* expr = MemberAccessor("str", "mem"); auto* expr = MemberAccessor("str", "mem");
WrapInFunction(Var("expr", ty.f32(), ast::StorageClass::kNone, expr)); WrapInFunction(Var("expr", ty.f32(), ast::StorageClass::kNone, expr));
@ -521,7 +522,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) {
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({
@ -567,7 +568,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({
@ -615,7 +616,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({
@ -663,7 +664,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({
@ -710,7 +711,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) {
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({
@ -755,7 +756,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
}); });
SetupStorageBuffer({ SetupStorageBuffer({
Member("c", ty.array(inner, 4, 32)), Member("c", ty.array(ty.Of(inner), 4, 32)),
}); });
SetupFunction({ SetupFunction({

View File

@ -34,7 +34,7 @@ TEST_F(HlslSanitizerTest, ArrayLength) {
create<ast::StructBlockDecoration>(), create<ast::StructBlockDecoration>(),
}); });
Global("sb", sb_ty, ast::StorageClass::kStorage, ast::Access::kRead, Global("sb", ty.Of(sb_ty), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -103,7 +103,7 @@ TEST_F(HlslSanitizerTest, PromoteStructInitializerToConstVar) {
Member("b", ty.vec3<f32>()), Member("b", ty.vec3<f32>()),
Member("c", ty.i32()), Member("c", ty.i32()),
}); });
auto* struct_init = Construct(str, 1, vec3<f32>(2.f, 3.f, 4.f), 4); auto* struct_init = Construct(ty.Of(str), 1, vec3<f32>(2.f, 3.f, 4.f), 4);
auto* struct_access = MemberAccessor(struct_init, "b"); auto* struct_access = MemberAccessor(struct_init, "b");
auto* pos = auto* pos =
Var("pos", ty.vec3<f32>(), ast::StorageClass::kNone, struct_access); Var("pos", ty.vec3<f32>(), ast::StorageClass::kNone, struct_access);

View File

@ -170,7 +170,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -190,7 +190,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl_OmittedIfStorageBuffer) {
Member("b", ty.f32()), Member("b", ty.f32()),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("g", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -208,7 +208,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -228,7 +228,7 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_InjectPadding) {
Member("b", ty.f32()), Member("b", ty.f32()),
Member("c", ty.f32(), {MemberAlign(128), MemberSize(128)}), Member("c", ty.f32(), {MemberAlign(128), MemberSize(128)}),
}); });
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -252,7 +252,7 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) {
Member("double", ty.i32()), Member("double", ty.i32()),
Member("float", ty.f32()), Member("float", ty.f32()),
}); });
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
GeneratorImpl& gen = SanitizeAndBuild(); GeneratorImpl& gen = SanitizeAndBuild();
@ -272,7 +272,7 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_WithDecoration) {
Member("b", ty.f32()), Member("b", ty.f32()),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("g", s, ast::StorageClass::kPrivate); Global("g", ty.Of(s), ast::StorageClass::kPrivate);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -41,7 +41,7 @@ TEST_F(HlslGeneratorImplTest_WorkgroupVar, Basic) {
TEST_F(HlslGeneratorImplTest_WorkgroupVar, Aliased) { TEST_F(HlslGeneratorImplTest_WorkgroupVar, Aliased) {
auto* alias = Alias("F32", ty.f32()); auto* alias = Alias("F32", ty.f32());
Global("wg", alias, ast::StorageClass::kWorkgroup); Global("wg", ty.Of(alias), ast::StorageClass::kWorkgroup);
Func("main", {}, ty.void_(), {Assign("wg", 1.2f)}, Func("main", {}, ty.void_(), {Assign("wg", 1.2f)},
{Stage(ast::PipelineStage::kCompute)}); {Stage(ast::PipelineStage::kCompute)});

View File

@ -87,9 +87,9 @@ bool GeneratorImpl::Generate() {
global_variables_.set(global->symbol(), sem); global_variables_.set(global->symbol(), sem);
} }
for (auto* const ty : program_->AST().ConstructedTypes()) { for (auto* const type_decl : program_->AST().ConstructedTypes()) {
if (!ty->Is<ast::Alias>()) { if (!type_decl->Is<ast::Alias>()) {
if (!EmitConstructedType(TypeOf(ty))) { if (!EmitConstructedType(TypeOf(type_decl))) {
return false; return false;
} }
} }

View File

@ -286,6 +286,12 @@ class GeneratorImpl : public TextGenerator {
return program_->TypeOf(type); return program_->TypeOf(type);
} }
/// @returns the resolved type of the ast::TypeDecl `type_decl`
/// @param type_decl the type declaration
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const {
return program_->TypeOf(type_decl);
}
// A pair of byte size and alignment `uint32_t`s. // A pair of byte size and alignment `uint32_t`s.
struct SizeAndAlign { struct SizeAndAlign {
uint32_t size; uint32_t size;

View File

@ -160,7 +160,7 @@ TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Struct) {
Member("c", ty.vec3<i32>()), Member("c", ty.vec3<i32>()),
}); });
WrapInFunction(Construct(str, 1, 2.0f, vec3<i32>(3, 4, 5))); WrapInFunction(Construct(ty.Of(str), 1, 2.0f, vec3<i32>(3, 4, 5)));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -171,7 +171,7 @@ TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Struct) {
TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Struct_Empty) { TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Struct_Empty) {
auto* str = Structure("S", {}); auto* str = Structure("S", {});
WrapInFunction(Construct(str)); WrapInFunction(Construct(ty.Of(str)));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -175,12 +175,12 @@ TEST_F(MslGeneratorImplTest,
Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)}), Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)}),
}); });
Func("vert_main", {}, interface_struct, Func("vert_main", {}, ty.Of(interface_struct),
{Return(Construct(interface_struct, Expr(0.5f), Expr(0.25f), {Return(Construct(ty.Of(interface_struct), Expr(0.5f), Expr(0.25f),
Construct(ty.vec4<f32>())))}, Construct(ty.vec4<f32>())))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("frag_main", {Param("colors", interface_struct)}, ty.void_(), Func("frag_main", {Param("colors", ty.Of(interface_struct))}, ty.void_(),
{ {
WrapInStatement( WrapInStatement(
Const("r", ty.f32(), MemberAccessor("colors", "col1"))), Const("r", ty.f32(), MemberAccessor("colors", "col1"))),
@ -246,16 +246,16 @@ TEST_F(MslGeneratorImplTest,
"VertexOutput", "VertexOutput",
{Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)})}); {Member("pos", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)})});
Func("foo", {Param("x", ty.f32())}, vertex_output_struct, Func("foo", {Param("x", ty.f32())}, ty.Of(vertex_output_struct),
{Return(Construct(vertex_output_struct, {Return(Construct(ty.Of(vertex_output_struct),
Construct(ty.vec4<f32>(), "x", "x", "x", Expr(1.f))))}, Construct(ty.vec4<f32>(), "x", "x", "x", Expr(1.f))))},
{}); {});
Func("vert_main1", {}, vertex_output_struct, Func("vert_main1", {}, ty.Of(vertex_output_struct),
{Return(Expr(Call("foo", Expr(0.5f))))}, {Return(Expr(Call("foo", Expr(0.5f))))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
Func("vert_main2", {}, vertex_output_struct, Func("vert_main2", {}, ty.Of(vertex_output_struct),
{Return(Expr(Call("foo", Expr(0.25f))))}, {Return(Expr(Call("foo", Expr(0.25f))))},
{Stage(ast::PipelineStage::kVertex)}); {Stage(ast::PipelineStage::kVertex)});
@ -306,7 +306,8 @@ TEST_F(MslGeneratorImplTest,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -352,7 +353,7 @@ TEST_F(MslGeneratorImplTest,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("coord", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -558,7 +559,7 @@ TEST_F(MslGeneratorImplTest,
Emit_Decoration_Called_By_EntryPoint_With_Uniform) { Emit_Decoration_Called_By_EntryPoint_With_Uniform) {
auto* ubo_ty = Structure("UBO", {Member("coord", ty.vec4<f32>())}, auto* ubo_ty = Structure("UBO", {Member("coord", ty.vec4<f32>())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* ubo = Global("ubo", ubo_ty, ast::StorageClass::kUniform, auto* ubo = Global("ubo", ty.Of(ubo_ty), ast::StorageClass::kUniform,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -616,7 +617,8 @@ TEST_F(MslGeneratorImplTest,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("coord", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -673,7 +675,7 @@ TEST_F(MslGeneratorImplTest,
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("coord", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("coord", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(1),
@ -816,7 +818,7 @@ TEST_F(MslGeneratorImplTest,
auto* s = Structure("Data", {Member("d", ty.f32())}, auto* s = Structure("Data", {Member("d", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("data", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("data", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -22,7 +22,7 @@ namespace {
using MslGeneratorImplTest = TestHelper; using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor) { TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor) {
Global("str", Structure("my_str", {Member("mem", ty.f32())}), Global("str", ty.Of(Structure("my_str", {Member("mem", ty.f32())})),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
auto* expr = MemberAccessor("str", "mem"); auto* expr = MemberAccessor("str", "mem");
WrapInFunction(expr); WrapInFunction(expr);

View File

@ -233,7 +233,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_NonComposites) {
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("G", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -335,14 +335,14 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_Structures) {
auto* s = Structure("S", auto* s = Structure("S",
{ {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", inner_x), Member("b", ty.Of(inner_x)),
Member("c", ty.f32()), Member("c", ty.f32()),
Member("d", inner_y), Member("d", ty.Of(inner_y)),
Member("e", ty.f32()), Member("e", ty.f32()),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("G", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -419,7 +419,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) {
auto* array_x = ty.array<f32, 7>(); auto* array_x = ty.array<f32, 7>();
// array_y: size(4096), align(512) // array_y: size(4096), align(512)
auto* array_y = ty.array(inner, 4); auto* array_y = ty.array(ty.Of(inner), 4);
// array_z: size(4), align(4) // array_z: size(4), align(4)
auto* array_z = ty.array<f32>(); auto* array_z = ty.array<f32>();
@ -436,7 +436,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) {
}, },
ast::DecorationList{create<ast::StructBlockDecoration>()}); ast::DecorationList{create<ast::StructBlockDecoration>()});
Global("G", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -549,7 +549,7 @@ TEST_F(MslGeneratorImplTest, AttemptTintPadSymbolCollision) {
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("G", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -614,7 +614,7 @@ TEST_F(MslGeneratorImplTest, DISABLED_EmitType_Struct_WithDecoration) {
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("G", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -70,7 +70,7 @@ TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Struct) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* var = Var("a", s, ast::StorageClass::kNone); auto* var = Var("a", ty.Of(s), ast::StorageClass::kNone);
auto* stmt = Decl(var); auto* stmt = Decl(var);
WrapInFunction(stmt); WrapInFunction(stmt);

View File

@ -224,7 +224,7 @@ TEST_F(BuilderTest, MemberAccessor) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* var = Var("ident", s); auto* var = Var("ident", ty.Of(s));
auto* expr = MemberAccessor("ident", "b"); auto* expr = MemberAccessor("ident", "b");
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -268,9 +268,9 @@ TEST_F(BuilderTest, MemberAccessor_Nested) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* s_type = Structure("my_struct", {Member("inner", inner_struct)}); auto* s_type = Structure("my_struct", {Member("inner", ty.Of(inner_struct))});
auto* var = Var("ident", s_type); auto* var = Var("ident", ty.Of(s_type));
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b"); auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b");
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -312,7 +312,7 @@ TEST_F(BuilderTest, MemberAccessor_NonPointer) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* var = Const("ident", s, Construct(s, 0.f, 0.f)); auto* var = Const("ident", ty.Of(s), Construct(ty.Of(s), 0.f, 0.f));
auto* expr = MemberAccessor("ident", "b"); auto* expr = MemberAccessor("ident", "b");
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -350,10 +350,11 @@ TEST_F(BuilderTest, MemberAccessor_Nested_NonPointer) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* s_type = Structure("my_struct", {Member("inner", inner_struct)}); auto* s_type = Structure("my_struct", {Member("inner", ty.Of(inner_struct))});
auto* var = Const("ident", s_type, auto* var =
Construct(s_type, Construct(inner_struct, 0.f, 0.f))); Const("ident", ty.Of(s_type),
Construct(ty.Of(s_type), Construct(ty.Of(inner_struct), 0.f, 0.f)));
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b"); auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b");
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -394,10 +395,10 @@ TEST_F(BuilderTest, MemberAccessor_Nested_WithAlias) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* alias = Alias("Alias", inner_struct); auto* alias = Alias("Alias", ty.Of(inner_struct));
auto* s_type = Structure("Outer", {Member("inner", alias)}); auto* s_type = Structure("Outer", {Member("inner", ty.Of(alias))});
auto* var = Var("ident", s_type); auto* var = Var("ident", ty.Of(s_type));
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "a"); auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "a");
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -440,9 +441,9 @@ TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_LHS) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* s_type = Structure("my_struct", {Member("inner", inner_struct)}); auto* s_type = Structure("my_struct", {Member("inner", ty.Of(inner_struct))});
auto* var = Var("ident", s_type); auto* var = Var("ident", ty.Of(s_type));
auto* expr = auto* expr =
Assign(MemberAccessor(MemberAccessor("ident", "inner"), "a"), Expr(2.0f)); Assign(MemberAccessor(MemberAccessor("ident", "inner"), "a"), Expr(2.0f));
WrapInFunction(var, expr); WrapInFunction(var, expr);
@ -489,9 +490,9 @@ TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_RHS) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* s_type = Structure("my_struct", {Member("inner", inner_struct)}); auto* s_type = Structure("my_struct", {Member("inner", ty.Of(inner_struct))});
auto* var = Var("ident", s_type); auto* var = Var("ident", ty.Of(s_type));
auto* store = Var("store", ty.f32()); auto* store = Var("store", ty.f32());
auto* rhs = MemberAccessor(MemberAccessor("ident", "inner"), "a"); auto* rhs = MemberAccessor(MemberAccessor("ident", "inner"), "a");
@ -696,11 +697,11 @@ TEST_F(BuilderTest, ArrayAccessor_Mixed_ArrayAndMember) {
auto* c_type = Structure("C", {Member("baz", ty.vec3<f32>())}); auto* c_type = Structure("C", {Member("baz", ty.vec3<f32>())});
auto* b_type = Structure("B", {Member("bar", c_type)}); auto* b_type = Structure("B", {Member("bar", ty.Of(c_type))});
auto* b_ary_type = ty.array(b_type, 3); auto* b_ary_type = ty.array(ty.Of(b_type), 3);
auto* a_type = Structure("A", {Member("foo", b_ary_type)}); auto* a_type = Structure("A", {Member("foo", b_ary_type)});
auto* a_ary_type = ty.array(a_type, 2); auto* a_ary_type = ty.array(ty.Of(a_type), 2);
auto* var = Var("index", a_ary_type); auto* var = Var("index", a_ary_type);
auto* expr = MemberAccessor( auto* expr = MemberAccessor(
MemberAccessor( MemberAccessor(

View File

@ -181,7 +181,7 @@ TEST_F(BuilderTest, Assign_StructMember) {
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* v = Var("ident", s); auto* v = Var("ident", ty.Of(s));
auto* assign = Assign(MemberAccessor("ident", "b"), Expr(4.f)); auto* assign = Assign(MemberAccessor("ident", "b"), Expr(4.f));

View File

@ -94,7 +94,7 @@ TEST_F(SpvBuilderConstructorTest, Type_WithAlias) {
// cast<Int>(2.3f) // cast<Int>(2.3f)
auto* alias = Alias("Int", ty.i32()); auto* alias = Alias("Int", ty.i32());
auto* cast = Construct(alias, 2.3f); auto* cast = Construct(ty.Of(alias), 2.3f);
WrapInFunction(cast); WrapInFunction(cast);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1056,7 +1056,7 @@ TEST_F(SpvBuilderConstructorTest, Type_Struct) {
Member("b", ty.vec3<f32>()), Member("b", ty.vec3<f32>()),
}); });
auto* t = Construct(s, 2.0f, vec3<f32>(2.0f, 2.0f, 2.0f)); auto* t = Construct(ty.Of(s), 2.0f, vec3<f32>(2.0f, 2.0f, 2.0f));
WrapInFunction(t); WrapInFunction(t);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1202,7 +1202,7 @@ TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Array) {
TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Struct) { TEST_F(SpvBuilderConstructorTest, Type_ZeroInit_Struct) {
auto* s = Structure("my_struct", {Member("a", ty.f32())}); auto* s = Structure("my_struct", {Member("a", ty.f32())});
auto* t = Construct(s); auto* t = Construct(ty.Of(s));
WrapInFunction(t); WrapInFunction(t);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1626,7 +1626,7 @@ TEST_F(SpvBuilderConstructorTest, IsConstructorConst_Struct) {
Member("b", ty.vec3<f32>()), Member("b", ty.vec3<f32>()),
}); });
auto* t = Construct(s, 2.f, vec3<f32>(2.f, 2.f, 2.f)); auto* t = Construct(ty.Of(s), 2.f, vec3<f32>(2.f, 2.f, 2.f));
WrapInFunction(t); WrapInFunction(t);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1645,7 +1645,7 @@ TEST_F(SpvBuilderConstructorTest,
Global("a", ty.f32(), ast::StorageClass::kPrivate); Global("a", ty.f32(), ast::StorageClass::kPrivate);
Global("b", ty.f32(), ast::StorageClass::kPrivate); Global("b", ty.f32(), ast::StorageClass::kPrivate);
auto* t = Construct(s, 2.f, "a", 2.f); auto* t = Construct(ty.Of(s), 2.f, "a", 2.f);
WrapInFunction(t); WrapInFunction(t);
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -196,11 +196,12 @@ TEST_F(BuilderTest, EntryPoint_SharedStruct) {
ast::DecorationList{Builtin(ast::Builtin::kPosition)}), ast::DecorationList{Builtin(ast::Builtin::kPosition)}),
}); });
auto* vert_retval = Construct(interface, 42.f, Construct(ty.vec4<f32>())); auto* vert_retval =
Func("vert_main", ast::VariableList{}, interface, {Return(vert_retval)}, Construct(ty.Of(interface), 42.f, Construct(ty.vec4<f32>()));
{Stage(ast::PipelineStage::kVertex)}); Func("vert_main", ast::VariableList{}, ty.Of(interface),
{Return(vert_retval)}, {Stage(ast::PipelineStage::kVertex)});
auto* frag_inputs = Param("inputs", interface); auto* frag_inputs = Param("inputs", ty.Of(interface));
Func("frag_main", ast::VariableList{frag_inputs}, ty.f32(), Func("frag_main", ast::VariableList{frag_inputs}, ty.f32(),
{Return(MemberAccessor(Expr("inputs"), "value"))}, {Return(MemberAccessor(Expr("inputs"), "value"))},
{Stage(ast::PipelineStage::kFragment)}, {Stage(ast::PipelineStage::kFragment)},

View File

@ -204,7 +204,7 @@ TEST_F(BuilderTest, Emit_Multiple_EntryPoint_With_Same_ModuleVar) {
auto* s = Structure("Data", {Member("d", ty.f32())}, auto* s = Structure("Data", {Member("d", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("data", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("data", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -403,11 +403,12 @@ TEST_F(BuilderTest, GlobalVar_DeclReadOnly) {
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* var = Global("b", A, ast::StorageClass::kStorage, ast::Access::kRead, auto* var =
ast::DecorationList{ Global("b", ty.Of(A), ast::StorageClass::kStorage, ast::Access::kRead,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -441,12 +442,13 @@ TEST_F(BuilderTest, GlobalVar_TypeAliasDeclReadOnly) {
auto* A = Structure("A", {Member("a", ty.i32())}, auto* A = Structure("A", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* B = Alias("B", A); auto* B = Alias("B", ty.Of(A));
auto* var = Global("b", B, ast::StorageClass::kStorage, ast::Access::kRead, auto* var =
ast::DecorationList{ Global("b", ty.Of(B), ast::StorageClass::kStorage, ast::Access::kRead,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -478,12 +480,13 @@ TEST_F(BuilderTest, GlobalVar_TypeAliasAssignReadOnly) {
auto* A = Structure("A", {Member("a", ty.i32())}, auto* A = Structure("A", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* B = Alias("B", A); auto* B = Alias("B", ty.Of(A));
auto* var = Global("b", B, ast::StorageClass::kStorage, ast::Access::kRead, auto* var =
ast::DecorationList{ Global("b", ty.Of(B), ast::StorageClass::kStorage, ast::Access::kRead,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -515,17 +518,18 @@ TEST_F(BuilderTest, GlobalVar_TwoVarDeclReadOnly) {
auto* A = Structure("A", {Member("a", ty.i32())}, auto* A = Structure("A", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* var_b = Global("b", A, ast::StorageClass::kStorage, ast::Access::kRead, auto* var_b =
ast::DecorationList{ Global("b", ty.Of(A), ast::StorageClass::kStorage, ast::Access::kRead,
create<ast::GroupDecoration>(0),
create<ast::BindingDecoration>(0),
});
auto* var_c =
Global("c", A, ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::GroupDecoration>(1), create<ast::GroupDecoration>(0),
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
}); });
auto* var_c = Global("c", ty.Of(A), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{
create<ast::GroupDecoration>(1),
create<ast::BindingDecoration>(0),
});
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -1537,7 +1537,7 @@ OpFunctionEnd
TEST_F(IntrinsicBuilderTest, Call_ArrayLength) { TEST_F(IntrinsicBuilderTest, Call_ArrayLength) {
auto* s = Structure("my_struct", {Member(0, "a", ty.array<f32>(4))}, auto* s = Structure("my_struct", {Member(0, "a", ty.array<f32>(4))},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("b", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(2), create<ast::GroupDecoration>(2),
@ -1586,7 +1586,7 @@ TEST_F(IntrinsicBuilderTest, Call_ArrayLength_OtherMembersInStruct) {
Member(4, "a", ty.array<f32>(4)), Member(4, "a", ty.array<f32>(4)),
}, },
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("b", s, ast::StorageClass::kStorage, ast::Access::kRead, Global("b", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(1), create<ast::BindingDecoration>(1),
create<ast::GroupDecoration>(2), create<ast::GroupDecoration>(2),

View File

@ -30,7 +30,7 @@ TEST_F(BuilderTest_Type, GenerateRuntimeArray) {
auto* ary = ty.array(ty.i32(), 0); auto* ary = ty.array(ty.i32(), 0);
auto* str = Structure("S", {Member("x", ary)}, auto* str = Structure("S", {Member("x", ary)},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("a", str, ast::StorageClass::kStorage, ast::Access::kRead, Global("a", ty.Of(str), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),
@ -51,7 +51,7 @@ TEST_F(BuilderTest_Type, ReturnsGeneratedRuntimeArray) {
auto* ary = ty.array(ty.i32(), 0); auto* ary = ty.array(ty.i32(), 0);
auto* str = Structure("S", {Member("x", ary)}, auto* str = Structure("S", {Member("x", ary)},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("a", str, ast::StorageClass::kStorage, ast::Access::kRead, Global("a", ty.Of(str), ast::StorageClass::kStorage, ast::Access::kRead,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -66,8 +66,8 @@ GeneratorImpl::~GeneratorImpl() = default;
bool GeneratorImpl::Generate() { bool GeneratorImpl::Generate() {
// Generate global declarations in the order they appear in the module. // Generate global declarations in the order they appear in the module.
for (auto* decl : program_->AST().GlobalDeclarations()) { for (auto* decl : program_->AST().GlobalDeclarations()) {
if (auto* ty = decl->As<ast::Type>()) { if (auto* td = decl->As<ast::TypeDecl>()) {
if (!EmitConstructedType(ty)) { if (!EmitConstructedType(td)) {
return false; return false;
} }
} else if (auto* func = decl->As<ast::Function>()) { } else if (auto* func = decl->As<ast::Function>()) {
@ -91,7 +91,7 @@ bool GeneratorImpl::Generate() {
return true; return true;
} }
bool GeneratorImpl::EmitConstructedType(const ast::Type* ty) { bool GeneratorImpl::EmitConstructedType(const ast::TypeDecl* ty) {
make_indent(); make_indent();
if (auto* alias = ty->As<ast::Alias>()) { if (auto* alias = ty->As<ast::Alias>()) {
@ -105,7 +105,8 @@ bool GeneratorImpl::EmitConstructedType(const ast::Type* ty) {
return false; return false;
} }
} else { } else {
diagnostics_.add_error("unknown constructed type: " + ty->type_name()); diagnostics_.add_error("unknown constructed type: " +
std::string(ty->TypeInfo().name));
return false; return false;
} }
return true; return true;
@ -374,9 +375,7 @@ bool GeneratorImpl::EmitAccess(const ast::Access access) {
} }
bool GeneratorImpl::EmitType(const ast::Type* ty) { bool GeneratorImpl::EmitType(const ast::Type* ty) {
if (auto* alias = ty->As<ast::Alias>()) { if (auto* ary = ty->As<ast::Array>()) {
out_ << program_->Symbols().NameFor(alias->symbol());
} else if (auto* ary = ty->As<ast::Array>()) {
for (auto* deco : ary->decorations()) { for (auto* deco : ary->decorations()) {
if (auto* stride = deco->As<ast::StrideDecoration>()) { if (auto* stride = deco->As<ast::StrideDecoration>()) {
out_ << "[[stride(" << stride->stride() << ")]] "; out_ << "[[stride(" << stride->stride() << ")]] ";
@ -416,10 +415,6 @@ bool GeneratorImpl::EmitType(const ast::Type* ty) {
if (sampler->IsComparison()) { if (sampler->IsComparison()) {
out_ << "_comparison"; out_ << "_comparison";
} }
} else if (auto* str = ty->As<ast::Struct>()) {
// The struct, as a type, is just the name. We should have already emitted
// the declaration through a call to |EmitStructType| earlier.
out_ << program_->Symbols().NameFor(str->name());
} else if (ty->Is<ast::ExternalTexture>()) { } else if (ty->Is<ast::ExternalTexture>()) {
out_ << "external_texture"; out_ << "external_texture";
} else if (auto* texture = ty->As<ast::Texture>()) { } else if (auto* texture = ty->As<ast::Texture>()) {

View File

@ -57,7 +57,7 @@ class GeneratorImpl : public TextGenerator {
/// Handles generating a constructed type /// Handles generating a constructed type
/// @param ty the constructed to generate /// @param ty the constructed to generate
/// @returns true if the constructed was emitted /// @returns true if the constructed was emitted
bool EmitConstructedType(const ast::Type* ty); bool EmitConstructedType(const ast::TypeDecl* ty);
/// Handles an array accessor expression /// Handles an array accessor expression
/// @param expr the expression to emit /// @param expr the expression to emit
/// @returns true if the array accessor was emitted /// @returns true if the array accessor was emitted

View File

@ -23,6 +23,7 @@ using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitAlias_F32) { TEST_F(WgslGeneratorImplTest, EmitAlias_F32) {
auto* alias = Alias("a", ty.f32()); auto* alias = Alias("a", ty.f32());
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitConstructedType(alias)) << gen.error(); ASSERT_TRUE(gen.EmitConstructedType(alias)) << gen.error();
@ -36,7 +37,7 @@ TEST_F(WgslGeneratorImplTest, EmitConstructedType_Struct) {
Member("b", ty.i32()), Member("b", ty.i32()),
}); });
auto* alias = Alias("B", s); auto* alias = Alias("B", ty.Of(s));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -56,7 +57,7 @@ TEST_F(WgslGeneratorImplTest, EmitAlias_ToStruct) {
Member("b", ty.i32()), Member("b", ty.i32()),
}); });
auto* alias = Alias("B", s); auto* alias = Alias("B", ty.Of(s));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -175,7 +175,7 @@ TEST_F(WgslGeneratorImplTest,
auto* s = Structure("Data", {Member("d", ty.f32())}, auto* s = Structure("Data", {Member("d", ty.f32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
Global("data", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, Global("data", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),

View File

@ -61,8 +61,8 @@ TEST_F(WgslGeneratorImplTest, Emit_GlobalsInterleaved) {
Func("main", ast::VariableList{}, ty.void_(), Func("main", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
Decl(Var("s0", s0)), Decl(Var("s0", ty.Of(s0))),
Decl(Var("s1", s1)), Decl(Var("s1", ty.Of(s1))),
Assign("a1", Call("func")), Assign("a1", Call("func")),
}, },
ast::DecorationList{ ast::DecorationList{

View File

@ -23,7 +23,7 @@ using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor) { TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor) {
auto* s = Structure("Data", {Member("mem", ty.f32())}); auto* s = Structure("Data", {Member("mem", ty.f32())});
Global("str", s, ast::StorageClass::kPrivate); Global("str", ty.Of(s), ast::StorageClass::kPrivate);
auto* expr = MemberAccessor("str", "mem"); auto* expr = MemberAccessor("str", "mem");
WrapInFunction(expr); WrapInFunction(expr);
@ -36,7 +36,7 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor) {
TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor_OfDref) { TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor_OfDref) {
auto* s = Structure("Data", {Member("mem", ty.f32())}); auto* s = Structure("Data", {Member("mem", ty.f32())});
Global("str", s, ast::StorageClass::kPrivate); Global("str", ty.Of(s), ast::StorageClass::kPrivate);
auto* p = Const("p", nullptr, AddressOf("str")); auto* p = Const("p", nullptr, AddressOf("str"));
auto* expr = MemberAccessor(Deref("p"), "mem"); auto* expr = MemberAccessor(Deref("p"), "mem");

View File

@ -27,10 +27,12 @@ using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitType_Alias) { TEST_F(WgslGeneratorImplTest, EmitType_Alias) {
auto* alias = Alias("alias", ty.f32()); auto* alias = Alias("alias", ty.f32());
auto* alias_ty = ty.Of(alias);
WrapInFunction(Var("make_reachable", alias_ty));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(alias)) << gen.error(); ASSERT_TRUE(gen.EmitType(alias_ty)) << gen.error();
EXPECT_EQ(gen.result(), "alias"); EXPECT_EQ(gen.result(), "alias");
} }
@ -119,10 +121,12 @@ TEST_F(WgslGeneratorImplTest, EmitType_Struct) {
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", ty.f32()), Member("b", ty.f32()),
}); });
auto* s_ty = ty.Of(s);
WrapInFunction(Var("make_reachable", s_ty));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(s)) << gen.error(); ASSERT_TRUE(gen.EmitType(s_ty)) << gen.error();
EXPECT_EQ(gen.result(), "S"); EXPECT_EQ(gen.result(), "S");
} }

View File

@ -46,11 +46,12 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_StorageClass) {
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Read) { TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Read) {
auto* s = Structure("S", {Member("a", ty.i32())}, auto* s = Structure("S", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* v = Global("a", s, ast::StorageClass::kStorage, ast::Access::kRead, auto* v =
ast::DecorationList{ Global("a", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -62,11 +63,12 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Read) {
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Write) { TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Write) {
auto* s = Structure("S", {Member("a", ty.i32())}, auto* s = Structure("S", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* v = Global("a", s, ast::StorageClass::kStorage, ast::Access::kWrite, auto* v =
ast::DecorationList{ Global("a", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kWrite,
create<ast::BindingDecoration>(0), ast::DecorationList{
create<ast::GroupDecoration>(0), create<ast::BindingDecoration>(0),
}); create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -78,7 +80,8 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Write) {
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_ReadWrite) { TEST_F(WgslGeneratorImplTest, EmitVariable_Access_ReadWrite) {
auto* s = Structure("S", {Member("a", ty.i32())}, auto* s = Structure("S", {Member("a", ty.i32())},
{create<ast::StructBlockDecoration>()}); {create<ast::StructBlockDecoration>()});
auto* v = Global("a", s, ast::StorageClass::kStorage, ast::Access::kReadWrite, auto* v = Global("a", ty.Of(s), ast::StorageClass::kStorage,
ast::Access::kReadWrite,
ast::DecorationList{ ast::DecorationList{
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0), create<ast::GroupDecoration>(0),