Rename StorageClass to AddressSpace.

This CL updates the internals to use AddressSpace instead of the old
StorageClass name.

Bug: tint:1404
Change-Id: Iecc208e839453437f4d630f65e0152206a52db7e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104420
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Auto-Submit: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2022-10-03 14:05:23 +00:00 committed by Dawn LUCI CQ
parent d5b64ecd78
commit ff7cf21021
300 changed files with 2696 additions and 2766 deletions

View File

@ -63,7 +63,7 @@ Quoting single word identifiers or keywords from the source is not discouraged.
**Don't:** **Don't:**
``` ```
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable shader.wgsl:5:11 error: type cannot be used in address space 'storage' as it is non-host-shareable
cond : bool; cond : bool;
^^^^ ^^^^
@ -72,7 +72,7 @@ shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is
**Do:** **Do:**
``` ```
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable shader.wgsl:5:11 error: type cannot be used in address space 'storage' as it is non-host-shareable
cond : bool; cond : bool;
^^^^ ^^^^

View File

@ -12,7 +12,7 @@ Specification work in the WebGPU group hasn't started.
## Pseudo-specification ## Pseudo-specification
This extension adds a new `push_constant` storage class that's only allowed on global variable declarations. This extension adds a new `push_constant` address space that's only allowed on global variable declarations.
Push constant variables must only contain 32bit data types (or aggregates of such types). Push constant variables must only contain 32bit data types (or aggregates of such types).
Push constant variable declarations must not have an initializer. Push constant variable declarations must not have an initializer.
It is an error for a entry point to statically use more than one `push_constant` variable. It is an error for a entry point to statically use more than one `push_constant` variable.

View File

@ -15,7 +15,7 @@ as variables at module scope.
## Vulkan SPIR-V today ## Vulkan SPIR-V today
SPIR-V for Vulkan models inputs and outputs as module-scope variables in SPIR-V for Vulkan models inputs and outputs as module-scope variables in
the Input and Output storage classes, respectively. the Input and Output address spaces, respectively.
The `OpEntryPoint` instruction has a list of module-scope variables that must The `OpEntryPoint` instruction has a list of module-scope variables that must
be a superset of all the input and output variables that are statically be a superset of all the input and output variables that are statically

View File

@ -141,7 +141,7 @@ TODO(dsinclair): Nested if's
## SPIR-V ## SPIR-V
TODO(dsinclair): Nested if's TODO(dsinclair): Nested if's
# Storage classes # Address spaces
TODO(dsinclair): do ... TODO(dsinclair): do ...
# Storage buffers # Storage buffers
@ -155,7 +155,7 @@ TODO(dsinclair): Rewrite with bools
## MSL ## MSL
TODO(dsinclair): Rewrite with bools TODO(dsinclair): Rewrite with bools
# Input / Output storage class # Input / Output address spaces
## HLSL ## HLSL
TODO(dsinclair): Structs and params TODO(dsinclair): Structs and params

View File

@ -42,7 +42,7 @@ ResultOrError<ComputePipelineBase*> GetOrCreateIndirectDispatchValidationPipelin
// TODO(https://crbug.com/dawn/1108): Propagate validation feedback from this // TODO(https://crbug.com/dawn/1108): Propagate validation feedback from this
// shader in various failure modes. // shader in various failure modes.
// Type 'bool' cannot be used in storage class 'uniform' as it is non-host-shareable. // Type 'bool' cannot be used in address space 'uniform' as it is non-host-shareable.
Ref<ShaderModuleBase> shaderModule; Ref<ShaderModuleBase> shaderModule;
DAWN_TRY_ASSIGN(shaderModule, utils::CreateShaderModule(device, R"( DAWN_TRY_ASSIGN(shaderModule, utils::CreateShaderModule(device, R"(
struct UniformParams { struct UniformParams {
@ -258,7 +258,7 @@ ComputePassEncoder::TransformIndirectDispatchBuffer(Ref<BufferBase> indirectBuff
kDispatchIndirectSize + clientOffsetFromAlignedBoundary; kDispatchIndirectSize + clientOffsetFromAlignedBoundary;
// Neither 'enableValidation' nor 'duplicateNumWorkgroups' can be declared as 'bool' as // Neither 'enableValidation' nor 'duplicateNumWorkgroups' can be declared as 'bool' as
// currently in WGSL type 'bool' cannot be used in storage class 'uniform' as 'it is // currently in WGSL type 'bool' cannot be used in address space 'uniform' as 'it is
// non-host-shareable'. // non-host-shareable'.
struct UniformParams { struct UniformParams {
uint32_t maxComputeWorkgroupsPerDimension; uint32_t maxComputeWorkgroupsPerDimension;

View File

@ -34,18 +34,18 @@ std::string ReplaceAll(std::string str, const std::string& substr, const std::st
return str; return str;
} }
// StorageClass is an enumerator of storage classes used by ComputeLayoutMemoryBufferTests.Fields // AddressSpace is an enumerator of address spaces used by ComputeLayoutMemoryBufferTests.Fields
enum class StorageClass { enum class AddressSpace {
Uniform, Uniform,
Storage, Storage,
}; };
std::ostream& operator<<(std::ostream& o, StorageClass storageClass) { std::ostream& operator<<(std::ostream& o, AddressSpace addressSpace) {
switch (storageClass) { switch (addressSpace) {
case StorageClass::Uniform: case AddressSpace::Uniform:
o << "uniform"; o << "uniform";
break; break;
case StorageClass::Storage: case AddressSpace::Storage:
o << "storage"; o << "storage";
break; break;
} }
@ -441,7 +441,7 @@ void RunComputeShaderWithBuffers(const wgpu::Device& device,
queue.Submit(1, &commands); queue.Submit(1, &commands);
} }
DAWN_TEST_PARAM_STRUCT(ComputeLayoutMemoryBufferTestParams, StorageClass, Field); DAWN_TEST_PARAM_STRUCT(ComputeLayoutMemoryBufferTestParams, AddressSpace, Field);
class ComputeLayoutMemoryBufferTests class ComputeLayoutMemoryBufferTests
: public DawnTestWithParams<ComputeLayoutMemoryBufferTestParams> { : public DawnTestWithParams<ComputeLayoutMemoryBufferTestParams> {
@ -472,7 +472,7 @@ TEST_P(ComputeLayoutMemoryBufferTests, StructMember) {
const Field& field = GetParam().mField; const Field& field = GetParam().mField;
const bool isUniform = GetParam().mStorageClass == StorageClass::Uniform; const bool isUniform = GetParam().mAddressSpace == AddressSpace::Uniform;
std::string shader = R"( std::string shader = R"(
struct Data { struct Data {
@ -619,7 +619,7 @@ TEST_P(ComputeLayoutMemoryBufferTests, NonStructMember) {
return; return;
} }
const bool isUniform = GetParam().mStorageClass == StorageClass::Uniform; const bool isUniform = GetParam().mAddressSpace == AddressSpace::Uniform;
std::string shader = R"( std::string shader = R"(
@group(0) @binding(0) var<{input_qualifiers}> input : {field_type}; @group(0) @binding(0) var<{input_qualifiers}> input : {field_type};
@ -685,7 +685,7 @@ auto GenerateParams() {
OpenGLBackend(), OpenGLBackend(),
OpenGLESBackend(), OpenGLESBackend(),
}, },
{StorageClass::Storage, StorageClass::Uniform}, {AddressSpace::Storage, AddressSpace::Uniform},
{ {
// See https://www.w3.org/TR/WGSL/#alignment-and-size // See https://www.w3.org/TR/WGSL/#alignment-and-size
// Scalar types with no custom alignment or size // Scalar types with no custom alignment or size
@ -851,7 +851,7 @@ auto GenerateParams() {
std::vector<ComputeLayoutMemoryBufferTestParams> filtered; std::vector<ComputeLayoutMemoryBufferTestParams> filtered;
for (auto param : params) { for (auto param : params) {
if (param.mStorageClass != StorageClass::Storage && param.mField.IsStorageBufferOnly()) { if (param.mAddressSpace != AddressSpace::Storage && param.mField.IsStorageBufferOnly()) {
continue; continue;
} }
filtered.emplace_back(param); filtered.emplace_back(param);

View File

@ -180,6 +180,8 @@ libtint_source_set("libtint_core_all_src") {
sources = [ sources = [
"ast/access.cc", "ast/access.cc",
"ast/access.h", "ast/access.h",
"ast/address_space.cc",
"ast/address_space.h",
"ast/alias.cc", "ast/alias.cc",
"ast/alias.h", "ast/alias.h",
"ast/array.cc", "ast/array.cc",
@ -312,8 +314,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/statement.h", "ast/statement.h",
"ast/static_assert.cc", "ast/static_assert.cc",
"ast/static_assert.h", "ast/static_assert.h",
"ast/storage_class.cc",
"ast/storage_class.h",
"ast/storage_texture.cc", "ast/storage_texture.cc",
"ast/storage_texture.h", "ast/storage_texture.h",
"ast/stride_attribute.cc", "ast/stride_attribute.cc",
@ -998,6 +998,7 @@ if (tint_build_unittests) {
tint_unittests_source_set("tint_unittests_ast_src") { tint_unittests_source_set("tint_unittests_ast_src") {
sources = [ sources = [
"ast/address_space_test.cc",
"ast/alias_test.cc", "ast/alias_test.cc",
"ast/array_test.cc", "ast/array_test.cc",
"ast/assignment_statement_test.cc", "ast/assignment_statement_test.cc",
@ -1054,7 +1055,6 @@ if (tint_build_unittests) {
"ast/sampler_test.cc", "ast/sampler_test.cc",
"ast/stage_attribute_test.cc", "ast/stage_attribute_test.cc",
"ast/static_assert_test.cc", "ast/static_assert_test.cc",
"ast/storage_class_test.cc",
"ast/storage_texture_test.cc", "ast/storage_texture_test.cc",
"ast/stride_attribute_test.cc", "ast/stride_attribute_test.cc",
"ast/struct_member_align_attribute_test.cc", "ast/struct_member_align_attribute_test.cc",
@ -1097,6 +1097,8 @@ if (tint_build_unittests) {
tint_unittests_source_set("tint_unittests_resolver_src") { tint_unittests_source_set("tint_unittests_resolver_src") {
sources = [ sources = [
"resolver/address_space_layout_validation_test.cc",
"resolver/address_space_validation_test.cc",
"resolver/array_accessor_test.cc", "resolver/array_accessor_test.cc",
"resolver/assignment_validation_test.cc", "resolver/assignment_validation_test.cc",
"resolver/atomics_test.cc", "resolver/atomics_test.cc",
@ -1133,11 +1135,9 @@ if (tint_build_unittests) {
"resolver/side_effects_test.cc", "resolver/side_effects_test.cc",
"resolver/source_variable_test.cc", "resolver/source_variable_test.cc",
"resolver/static_assert_test.cc", "resolver/static_assert_test.cc",
"resolver/storage_class_layout_validation_test.cc", "resolver/struct_address_space_use_test.cc",
"resolver/storage_class_validation_test.cc",
"resolver/struct_layout_test.cc", "resolver/struct_layout_test.cc",
"resolver/struct_pipeline_stage_use_test.cc", "resolver/struct_pipeline_stage_use_test.cc",
"resolver/struct_storage_class_use_test.cc",
"resolver/type_constructor_validation_test.cc", "resolver/type_constructor_validation_test.cc",
"resolver/type_validation_test.cc", "resolver/type_validation_test.cc",
"resolver/uniformity_test.cc", "resolver/uniformity_test.cc",
@ -1354,6 +1354,7 @@ if (tint_build_unittests) {
sources = [ sources = [
"reader/wgsl/lexer_test.cc", "reader/wgsl/lexer_test.cc",
"reader/wgsl/parser_impl_additive_expression_test.cc", "reader/wgsl/parser_impl_additive_expression_test.cc",
"reader/wgsl/parser_impl_address_space_test.cc",
"reader/wgsl/parser_impl_argument_expression_list_test.cc", "reader/wgsl/parser_impl_argument_expression_list_test.cc",
"reader/wgsl/parser_impl_assignment_stmt_test.cc", "reader/wgsl/parser_impl_assignment_stmt_test.cc",
"reader/wgsl/parser_impl_bitwise_expression_test.cc", "reader/wgsl/parser_impl_bitwise_expression_test.cc",
@ -1400,7 +1401,6 @@ if (tint_build_unittests) {
"reader/wgsl/parser_impl_singular_expression_test.cc", "reader/wgsl/parser_impl_singular_expression_test.cc",
"reader/wgsl/parser_impl_statement_test.cc", "reader/wgsl/parser_impl_statement_test.cc",
"reader/wgsl/parser_impl_statements_test.cc", "reader/wgsl/parser_impl_statements_test.cc",
"reader/wgsl/parser_impl_storage_class_test.cc",
"reader/wgsl/parser_impl_storage_texture_test.cc", "reader/wgsl/parser_impl_storage_texture_test.cc",
"reader/wgsl/parser_impl_struct_attribute_decl_test.cc", "reader/wgsl/parser_impl_struct_attribute_decl_test.cc",
"reader/wgsl/parser_impl_struct_body_decl_test.cc", "reader/wgsl/parser_impl_struct_body_decl_test.cc",

View File

@ -182,8 +182,8 @@ set(TINT_LIB_SRCS
ast/statement.h ast/statement.h
ast/static_assert.cc ast/static_assert.cc
ast/static_assert.h ast/static_assert.h
ast/storage_class.cc ast/address_space.cc
ast/storage_class.h ast/address_space.h
ast/storage_texture.cc ast/storage_texture.cc
ast/storage_texture.h ast/storage_texture.h
ast/stride_attribute.cc ast/stride_attribute.cc
@ -747,7 +747,7 @@ if(TINT_BUILD_TESTS)
ast/sampler_test.cc ast/sampler_test.cc
ast/stage_attribute_test.cc ast/stage_attribute_test.cc
ast/static_assert_test.cc ast/static_assert_test.cc
ast/storage_class_test.cc ast/address_space_test.cc
ast/storage_texture_test.cc ast/storage_texture_test.cc
ast/stride_attribute_test.cc ast/stride_attribute_test.cc
ast/struct_member_align_attribute_test.cc ast/struct_member_align_attribute_test.cc
@ -814,11 +814,11 @@ if(TINT_BUILD_TESTS)
resolver/side_effects_test.cc resolver/side_effects_test.cc
resolver/static_assert_test.cc resolver/static_assert_test.cc
resolver/source_variable_test.cc resolver/source_variable_test.cc
resolver/storage_class_layout_validation_test.cc resolver/address_space_layout_validation_test.cc
resolver/storage_class_validation_test.cc resolver/address_space_validation_test.cc
resolver/struct_layout_test.cc resolver/struct_layout_test.cc
resolver/struct_pipeline_stage_use_test.cc resolver/struct_pipeline_stage_use_test.cc
resolver/struct_storage_class_use_test.cc resolver/struct_address_space_use_test.cc
resolver/type_constructor_validation_test.cc resolver/type_constructor_validation_test.cc
resolver/type_validation_test.cc resolver/type_validation_test.cc
resolver/validation_test.cc resolver/validation_test.cc
@ -992,7 +992,7 @@ if(TINT_BUILD_TESTS)
reader/wgsl/parser_impl_singular_expression_test.cc reader/wgsl/parser_impl_singular_expression_test.cc
reader/wgsl/parser_impl_statement_test.cc reader/wgsl/parser_impl_statement_test.cc
reader/wgsl/parser_impl_statements_test.cc reader/wgsl/parser_impl_statements_test.cc
reader/wgsl/parser_impl_storage_class_test.cc reader/wgsl/parser_impl_address_space_test.cc
reader/wgsl/parser_impl_storage_texture_test.cc reader/wgsl/parser_impl_storage_texture_test.cc
reader/wgsl/parser_impl_struct_body_decl_test.cc reader/wgsl/parser_impl_struct_body_decl_test.cc
reader/wgsl/parser_impl_struct_decl_test.cc reader/wgsl/parser_impl_struct_decl_test.cc
@ -1300,7 +1300,7 @@ if(TINT_BUILD_BENCHMARKS)
set(TINT_BENCHMARK_SRC set(TINT_BENCHMARK_SRC
"castable_bench.cc" "castable_bench.cc"
"ast/extension_bench.cc" "ast/extension_bench.cc"
"ast/storage_class_bench.cc" "ast/address_space_bench.cc"
"ast/texel_format_bench.cc" "ast/texel_format_bench.cc"
"bench/benchmark.cc" "bench/benchmark.cc"
"reader/wgsl/parser_bench.cc" "reader/wgsl/parser_bench.cc"

View File

@ -15,63 +15,63 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen // File generated by tools/src/cmd/gen
// using the template: // using the template:
// src/tint/ast/storage_class.cc.tmpl // src/tint/ast/address_space.cc.tmpl
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
namespace tint::ast { namespace tint::ast {
/// ParseStorageClass parses a StorageClass from a string. /// ParseAddressSpace parses a AddressSpace from a string.
/// @param str the string to parse /// @param str the string to parse
/// @returns the parsed enum, or StorageClass::kInvalid if the string could not be parsed. /// @returns the parsed enum, or AddressSpace::kInvalid if the string could not be parsed.
StorageClass ParseStorageClass(std::string_view str) { AddressSpace ParseAddressSpace(std::string_view str) {
if (str == "function") { if (str == "function") {
return StorageClass::kFunction; return AddressSpace::kFunction;
} }
if (str == "private") { if (str == "private") {
return StorageClass::kPrivate; return AddressSpace::kPrivate;
} }
if (str == "workgroup") { if (str == "workgroup") {
return StorageClass::kWorkgroup; return AddressSpace::kWorkgroup;
} }
if (str == "uniform") { if (str == "uniform") {
return StorageClass::kUniform; return AddressSpace::kUniform;
} }
if (str == "storage") { if (str == "storage") {
return StorageClass::kStorage; return AddressSpace::kStorage;
} }
if (str == "push_constant") { if (str == "push_constant") {
return StorageClass::kPushConstant; return AddressSpace::kPushConstant;
} }
return StorageClass::kInvalid; return AddressSpace::kInvalid;
} }
std::ostream& operator<<(std::ostream& out, StorageClass value) { std::ostream& operator<<(std::ostream& out, AddressSpace value) {
switch (value) { switch (value) {
case StorageClass::kInvalid: case AddressSpace::kInvalid:
return out << "invalid"; return out << "invalid";
case StorageClass::kNone: case AddressSpace::kNone:
return out << "none"; return out << "none";
case StorageClass::kFunction: case AddressSpace::kFunction:
return out << "function"; return out << "function";
case StorageClass::kPrivate: case AddressSpace::kPrivate:
return out << "private"; return out << "private";
case StorageClass::kWorkgroup: case AddressSpace::kWorkgroup:
return out << "workgroup"; return out << "workgroup";
case StorageClass::kUniform: case AddressSpace::kUniform:
return out << "uniform"; return out << "uniform";
case StorageClass::kStorage: case AddressSpace::kStorage:
return out << "storage"; return out << "storage";
case StorageClass::kPushConstant: case AddressSpace::kPushConstant:
return out << "push_constant"; return out << "push_constant";
case StorageClass::kHandle: case AddressSpace::kHandle:
return out << "handle"; return out << "handle";
case StorageClass::kIn: case AddressSpace::kIn:
return out << "in"; return out << "in";
case StorageClass::kOut: case AddressSpace::kOut:
return out << "out"; return out << "out";
} }
return out << "<unknown>"; return out << "<unknown>";

View File

@ -1,6 +1,6 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate storage_class.cc Template file for use with tools/src/cmd/gen to generate address_space.cc
To update the generated file, run: To update the generated file, run:
./tools/run gen ./tools/run gen
@ -12,9 +12,9 @@ See:
*/ -}} */ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}} {{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "storage_class") -}} {{- $enum := (Sem.Enum "address_space") -}}
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
namespace tint::ast { namespace tint::ast {

View File

@ -15,20 +15,20 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen // File generated by tools/src/cmd/gen
// using the template: // using the template:
// src/tint/ast/storage_class.h.tmpl // src/tint/ast/address_space.h.tmpl
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef SRC_TINT_AST_STORAGE_CLASS_H_ #ifndef SRC_TINT_AST_ADDRESS_SPACE_H_
#define SRC_TINT_AST_STORAGE_CLASS_H_ #define SRC_TINT_AST_ADDRESS_SPACE_H_
#include <ostream> #include <ostream>
namespace tint::ast { namespace tint::ast {
/// Storage class of a given pointer. /// Address space of a given pointer.
enum class StorageClass { enum class AddressSpace {
kInvalid, kInvalid,
kNone, // Tint-internal enum entry - not parsed kNone, // Tint-internal enum entry - not parsed
kFunction, kFunction,
@ -43,23 +43,24 @@ enum class StorageClass {
}; };
/// @param out the std::ostream to write to /// @param out the std::ostream to write to
/// @param value the StorageClass /// @param value the AddressSpace
/// @returns `out` so calls can be chained /// @returns `out` so calls can be chained
std::ostream& operator<<(std::ostream& out, StorageClass value); std::ostream& operator<<(std::ostream& out, AddressSpace value);
/// ParseStorageClass parses a StorageClass from a string. /// ParseAddressSpace parses a AddressSpace from a string.
/// @param str the string to parse /// @param str the string to parse
/// @returns the parsed enum, or StorageClass::kInvalid if the string could not be parsed. /// @returns the parsed enum, or AddressSpace::kInvalid if the string could not be parsed.
StorageClass ParseStorageClass(std::string_view str); AddressSpace ParseAddressSpace(std::string_view str);
/// @returns true if the StorageClass is host-shareable /// @returns true if the AddressSpace is host-shareable
/// @param sc the StorageClass /// @param address_space the AddressSpace
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable /// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
inline bool IsHostShareable(StorageClass sc) { inline bool IsHostShareable(AddressSpace address_space) {
return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage || return address_space == ast::AddressSpace::kUniform ||
sc == ast::StorageClass::kPushConstant; address_space == ast::AddressSpace::kStorage ||
address_space == ast::AddressSpace::kPushConstant;
} }
} // namespace tint::ast } // namespace tint::ast
#endif // SRC_TINT_AST_STORAGE_CLASS_H_ #endif // SRC_TINT_AST_ADDRESS_SPACE_H_

View File

@ -1,6 +1,6 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate storage_class.h Template file for use with tools/src/cmd/gen to generate address_space.h
To update the generated file, run: To update the generated file, run:
./tools/run gen ./tools/run gen
@ -12,26 +12,26 @@ See:
*/ -}} */ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}} {{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "storage_class") -}} {{- $enum := (Sem.Enum "address_space") -}}
#ifndef SRC_TINT_AST_STORAGE_CLASS_H_ #ifndef SRC_TINT_AST_ADDRESS_SPACE_H_
#define SRC_TINT_AST_STORAGE_CLASS_H_ #define SRC_TINT_AST_ADDRESS_SPACE_H_
#include <ostream> #include <ostream>
namespace tint::ast { namespace tint::ast {
/// Storage class of a given pointer. /// Address space of a given pointer.
{{ Eval "DeclareEnum" $enum}} {{ Eval "DeclareEnum" $enum}}
/// @returns true if the StorageClass is host-shareable /// @returns true if the AddressSpace is host-shareable
/// @param sc the StorageClass /// @param address_space the AddressSpace
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable /// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
inline bool IsHostShareable(StorageClass sc) { inline bool IsHostShareable(AddressSpace address_space) {
return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage || return address_space == ast::AddressSpace::kUniform || address_space == ast::AddressSpace::kStorage ||
sc == ast::StorageClass::kPushConstant; address_space == ast::AddressSpace::kPushConstant;
} }
} // namespace tint::ast } // namespace tint::ast
#endif // SRC_TINT_AST_STORAGE_CLASS_H_ #endif // SRC_TINT_AST_ADDRESS_SPACE_H_

View File

@ -15,12 +15,12 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen // File generated by tools/src/cmd/gen
// using the template: // using the template:
// src/tint/ast/storage_class_bench.cc.tmpl // src/tint/ast/address_space_bench.cc.tmpl
// //
// Do not modify this file directly // Do not modify this file directly
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
#include <array> #include <array>
@ -29,7 +29,7 @@
namespace tint::ast { namespace tint::ast {
namespace { namespace {
void StorageClassParser(::benchmark::State& state) { void AddressSpaceParser(::benchmark::State& state) {
std::array kStrings{ std::array kStrings{
"fccnctin", "fccnctin",
"ucti3", "ucti3",
@ -76,13 +76,13 @@ void StorageClassParser(::benchmark::State& state) {
}; };
for (auto _ : state) { for (auto _ : state) {
for (auto& str : kStrings) { for (auto& str : kStrings) {
auto result = ParseStorageClass(str); auto result = ParseAddressSpace(str);
benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(result);
} }
} }
} }
BENCHMARK(StorageClassParser); BENCHMARK(AddressSpaceParser);
} // namespace } // namespace
} // namespace tint::ast } // namespace tint::ast

View File

@ -1,6 +1,6 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate storage_class_bench.cc Template file for use with tools/src/cmd/gen to generate address_space_bench.cc
To update the generated file, run: To update the generated file, run:
./tools/run gen ./tools/run gen
@ -12,9 +12,9 @@ See:
*/ -}} */ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}} {{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "storage_class") -}} {{- $enum := (Sem.Enum "address_space") -}}
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
#include <array> #include <array>

View File

@ -0,0 +1,86 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/address_space_test.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/address_space.h"
#include <string>
#include "src/tint/ast/test_helper.h"
#include "src/tint/utils/string.h"
namespace tint::ast {
namespace {
namespace parse_print_tests {
struct Case {
const char* string;
AddressSpace value;
};
inline std::ostream& operator<<(std::ostream& out, Case c) {
return out << "'" << std::string(c.string) << "'";
}
static constexpr Case kValidCases[] = {
{"function", AddressSpace::kFunction}, {"private", AddressSpace::kPrivate},
{"workgroup", AddressSpace::kWorkgroup}, {"uniform", AddressSpace::kUniform},
{"storage", AddressSpace::kStorage}, {"push_constant", AddressSpace::kPushConstant},
};
static constexpr Case kInvalidCases[] = {
{"fccnctin", AddressSpace::kInvalid}, {"ucti3", AddressSpace::kInvalid},
{"functVon", AddressSpace::kInvalid}, {"priv1te", AddressSpace::kInvalid},
{"pqiJate", AddressSpace::kInvalid}, {"privat7ll", AddressSpace::kInvalid},
{"workroppqHH", AddressSpace::kInvalid}, {"workru", AddressSpace::kInvalid},
{"wbkgGoup", AddressSpace::kInvalid}, {"unifiivm", AddressSpace::kInvalid},
{"8WWiform", AddressSpace::kInvalid}, {"uxxform", AddressSpace::kInvalid},
{"sXraggg", AddressSpace::kInvalid}, {"traXe", AddressSpace::kInvalid},
{"stor3ge", AddressSpace::kInvalid}, {"push_constanE", AddressSpace::kInvalid},
{"push_TTPnstant", AddressSpace::kInvalid}, {"puxxdh_constan", AddressSpace::kInvalid},
};
using AddressSpaceParseTest = testing::TestWithParam<Case>;
TEST_P(AddressSpaceParseTest, Parse) {
const char* string = GetParam().string;
AddressSpace expect = GetParam().value;
EXPECT_EQ(expect, ParseAddressSpace(string));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, AddressSpaceParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, AddressSpaceParseTest, testing::ValuesIn(kInvalidCases));
using AddressSpacePrintTest = testing::TestWithParam<Case>;
TEST_P(AddressSpacePrintTest, Print) {
AddressSpace value = GetParam().value;
const char* expect = GetParam().string;
EXPECT_EQ(expect, utils::ToString(value));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, AddressSpacePrintTest, testing::ValuesIn(kValidCases));
} // namespace parse_print_tests
} // namespace
} // namespace tint::ast

View File

@ -1,6 +1,6 @@
{{- /* {{- /*
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Template file for use with tools/src/cmd/gen to generate storage_class_test.cc Template file for use with tools/src/cmd/gen to generate address_space_test.cc
To update the generated file, run: To update the generated file, run:
./tools/run gen ./tools/run gen
@ -12,9 +12,9 @@ See:
*/ -}} */ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}} {{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "storage_class") -}} {{- $enum := (Sem.Enum "address_space") -}}
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
#include <string> #include <string>

View File

@ -33,8 +33,8 @@ std::string DisableValidationAttribute::InternalName() const {
return "disable_validation__function_has_no_body"; return "disable_validation__function_has_no_body";
case DisabledValidation::kBindingPointCollision: case DisabledValidation::kBindingPointCollision:
return "disable_validation__binding_point_collision"; return "disable_validation__binding_point_collision";
case DisabledValidation::kIgnoreStorageClass: case DisabledValidation::kIgnoreAddressSpace:
return "disable_validation__ignore_storage_class"; return "disable_validation__ignore_address_space";
case DisabledValidation::kEntryPointParameter: case DisabledValidation::kEntryPointParameter:
return "disable_validation__entry_point_parameter"; return "disable_validation__entry_point_parameter";
case DisabledValidation::kFunctionParameter: case DisabledValidation::kFunctionParameter:

View File

@ -29,9 +29,9 @@ enum class DisabledValidation {
/// When applied to a module-scoped variable, the validator will not complain if two resource /// When applied to a module-scoped variable, the validator will not complain if two resource
/// variables have the same binding points. /// variables have the same binding points.
kBindingPointCollision, kBindingPointCollision,
/// When applied to a variable, the validator will not complain about the declared storage /// When applied to a variable, the validator will not complain about the declared address
/// class. /// space.
kIgnoreStorageClass, kIgnoreAddressSpace,
/// When applied to an entry-point function parameter, the validator will not check for entry IO /// When applied to an entry-point function parameter, the validator will not check for entry IO
/// attributes. /// attributes.
kEntryPointParameter, kEntryPointParameter,

View File

@ -72,7 +72,7 @@ TEST_F(ModuleTest, Assert_DifferentProgramID_GlobalVariable) {
{ {
ProgramBuilder b1; ProgramBuilder b1;
ProgramBuilder b2; ProgramBuilder b2;
b1.AST().AddGlobalVariable(b2.Var("var", b2.ty.i32(), ast::StorageClass::kPrivate)); b1.AST().AddGlobalVariable(b2.Var("var", b2.ty.i32(), ast::AddressSpace::kPrivate));
}, },
"internal compiler error"); "internal compiler error");
} }
@ -92,7 +92,7 @@ TEST_F(ModuleTest, CloneOrder) {
ProgramBuilder b; ProgramBuilder b;
b.Func("F", {}, b.ty.void_(), {}); b.Func("F", {}, b.ty.void_(), {});
b.Alias("A", b.ty.u32()); b.Alias("A", b.ty.u32());
b.GlobalVar("V", b.ty.i32(), ast::StorageClass::kPrivate); b.GlobalVar("V", b.ty.i32(), ast::AddressSpace::kPrivate);
return Program(std::move(b)); return Program(std::move(b));
}(); }();

View File

@ -24,15 +24,15 @@ Pointer::Pointer(ProgramID pid,
NodeID nid, NodeID nid,
const Source& src, const Source& src,
const Type* const subtype, const Type* const subtype,
ast::StorageClass sc, ast::AddressSpace addr_space,
ast::Access ac) ast::Access ac)
: Base(pid, nid, src), type(subtype), storage_class(sc), access(ac) {} : Base(pid, nid, src), type(subtype), address_space(addr_space), access(ac) {}
std::string Pointer::FriendlyName(const SymbolTable& symbols) const { std::string Pointer::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out; std::ostringstream out;
out << "ptr<"; out << "ptr<";
if (storage_class != ast::StorageClass::kNone) { if (address_space != ast::AddressSpace::kNone) {
out << storage_class << ", "; out << address_space << ", ";
} }
out << type->FriendlyName(symbols); out << type->FriendlyName(symbols);
if (access != ast::Access::kUndefined) { if (access != ast::Access::kUndefined) {
@ -50,7 +50,7 @@ const Pointer* Pointer::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source); auto src = ctx->Clone(source);
auto* ty = ctx->Clone(type); auto* ty = ctx->Clone(type);
return ctx->dst->create<Pointer>(src, ty, storage_class, access); return ctx->dst->create<Pointer>(src, ty, address_space, access);
} }
} // namespace tint::ast } // namespace tint::ast

View File

@ -18,7 +18,7 @@
#include <string> #include <string>
#include "src/tint/ast/access.h" #include "src/tint/ast/access.h"
#include "src/tint/ast/storage_class.h" #include "src/tint/ast/address_space.h"
#include "src/tint/ast/type.h" #include "src/tint/ast/type.h"
namespace tint::ast { namespace tint::ast {
@ -31,13 +31,13 @@ class Pointer final : public Castable<Pointer, Type> {
/// @param nid the unique node identifier /// @param nid the unique node identifier
/// @param src the source of this node /// @param src the source of this node
/// @param subtype the pointee type /// @param subtype the pointee type
/// @param storage_class the storage class of the pointer /// @param address_space the address space of the pointer
/// @param access the access control of the pointer /// @param access the access control of the pointer
Pointer(ProgramID pid, Pointer(ProgramID pid,
NodeID nid, NodeID nid,
const Source& src, const Source& src,
const Type* const subtype, const Type* const subtype,
ast::StorageClass storage_class, ast::AddressSpace address_space,
ast::Access access); ast::Access access);
/// Move constructor /// Move constructor
Pointer(Pointer&&); Pointer(Pointer&&);
@ -56,8 +56,8 @@ class Pointer final : public Castable<Pointer, Type> {
/// The pointee type /// The pointee type
const Type* const type; const Type* const type;
/// The storage class of the pointer /// The address space of the pointer
ast::StorageClass const storage_class; ast::AddressSpace const address_space;
/// The access control of the pointer /// The access control of the pointer
ast::Access const access; ast::Access const access;

View File

@ -24,21 +24,21 @@ using AstPointerTest = TestHelper;
TEST_F(AstPointerTest, Creation) { TEST_F(AstPointerTest, Creation) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kStorage, Access::kRead); auto* p = create<Pointer>(i32, ast::AddressSpace::kStorage, Access::kRead);
EXPECT_EQ(p->type, i32); EXPECT_EQ(p->type, i32);
EXPECT_EQ(p->storage_class, ast::StorageClass::kStorage); EXPECT_EQ(p->address_space, ast::AddressSpace::kStorage);
EXPECT_EQ(p->access, Access::kRead); EXPECT_EQ(p->access, Access::kRead);
} }
TEST_F(AstPointerTest, FriendlyName) { TEST_F(AstPointerTest, FriendlyName) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kWorkgroup, Access::kUndefined); auto* p = create<Pointer>(i32, ast::AddressSpace::kWorkgroup, Access::kUndefined);
EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>"); EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>");
} }
TEST_F(AstPointerTest, FriendlyNameWithAccess) { TEST_F(AstPointerTest, FriendlyNameWithAccess) {
auto* i32 = create<I32>(); auto* i32 = create<I32>();
auto* p = create<Pointer>(i32, ast::StorageClass::kStorage, Access::kReadWrite); auto* p = create<Pointer>(i32, ast::AddressSpace::kStorage, Access::kReadWrite);
EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<storage, i32, read_write>"); EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<storage, i32, read_write>");
} }

View File

@ -1,86 +0,0 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/storage_class_test.cc.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/storage_class.h"
#include <string>
#include "src/tint/ast/test_helper.h"
#include "src/tint/utils/string.h"
namespace tint::ast {
namespace {
namespace parse_print_tests {
struct Case {
const char* string;
StorageClass value;
};
inline std::ostream& operator<<(std::ostream& out, Case c) {
return out << "'" << std::string(c.string) << "'";
}
static constexpr Case kValidCases[] = {
{"function", StorageClass::kFunction}, {"private", StorageClass::kPrivate},
{"workgroup", StorageClass::kWorkgroup}, {"uniform", StorageClass::kUniform},
{"storage", StorageClass::kStorage}, {"push_constant", StorageClass::kPushConstant},
};
static constexpr Case kInvalidCases[] = {
{"fccnctin", StorageClass::kInvalid}, {"ucti3", StorageClass::kInvalid},
{"functVon", StorageClass::kInvalid}, {"priv1te", StorageClass::kInvalid},
{"pqiJate", StorageClass::kInvalid}, {"privat7ll", StorageClass::kInvalid},
{"workroppqHH", StorageClass::kInvalid}, {"workru", StorageClass::kInvalid},
{"wbkgGoup", StorageClass::kInvalid}, {"unifiivm", StorageClass::kInvalid},
{"8WWiform", StorageClass::kInvalid}, {"uxxform", StorageClass::kInvalid},
{"sXraggg", StorageClass::kInvalid}, {"traXe", StorageClass::kInvalid},
{"stor3ge", StorageClass::kInvalid}, {"push_constanE", StorageClass::kInvalid},
{"push_TTPnstant", StorageClass::kInvalid}, {"puxxdh_constan", StorageClass::kInvalid},
};
using StorageClassParseTest = testing::TestWithParam<Case>;
TEST_P(StorageClassParseTest, Parse) {
const char* string = GetParam().string;
StorageClass expect = GetParam().value;
EXPECT_EQ(expect, ParseStorageClass(string));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, StorageClassParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, StorageClassParseTest, testing::ValuesIn(kInvalidCases));
using StorageClassPrintTest = testing::TestWithParam<Case>;
TEST_P(StorageClassPrintTest, Print) {
StorageClass value = GetParam().value;
const char* expect = GetParam().string;
EXPECT_EQ(expect, utils::ToString(value));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, StorageClassPrintTest, testing::ValuesIn(kValidCases));
} // namespace parse_print_tests
} // namespace
} // namespace tint::ast

View File

@ -25,12 +25,12 @@ Var::Var(ProgramID pid,
const Source& src, const Source& src,
const Symbol& sym, const Symbol& sym,
const ast::Type* ty, const ast::Type* ty,
StorageClass storage_class, AddressSpace address_space,
Access access, Access access,
const Expression* ctor, const Expression* ctor,
utils::VectorRef<const Attribute*> attrs) utils::VectorRef<const Attribute*> attrs)
: Base(pid, nid, src, sym, ty, ctor, std::move(attrs)), : Base(pid, nid, src, sym, ty, ctor, std::move(attrs)),
declared_storage_class(storage_class), declared_address_space(address_space),
declared_access(access) {} declared_access(access) {}
Var::Var(Var&&) = default; Var::Var(Var&&) = default;
@ -47,7 +47,7 @@ const Var* Var::Clone(CloneContext* ctx) const {
auto* ty = ctx->Clone(type); auto* ty = ctx->Clone(type);
auto* ctor = ctx->Clone(constructor); auto* ctor = ctx->Clone(constructor);
auto attrs = ctx->Clone(attributes); auto attrs = ctx->Clone(attributes);
return ctx->dst->create<Var>(src, sym, ty, declared_storage_class, declared_access, ctor, return ctx->dst->create<Var>(src, sym, ty, declared_address_space, declared_access, ctor,
std::move(attrs)); std::move(attrs));
} }

View File

@ -28,11 +28,11 @@ namespace tint::ast {
/// ///
/// ``` /// ```
/// // Declared outside a function, i.e. at module scope, requires /// // Declared outside a function, i.e. at module scope, requires
/// // a storage class. /// // a address space.
/// var<workgroup> width : i32; // no initializer /// var<workgroup> width : i32; // no initializer
/// var<private> height : i32 = 3; // with initializer /// var<private> height : i32 = 3; // with initializer
/// ///
/// // A variable declared inside a function doesn't take a storage class, /// // A variable declared inside a function doesn't take a address space,
/// // and maps to SPIR-V Function storage. /// // and maps to SPIR-V Function storage.
/// var computed_depth : i32; /// var computed_depth : i32;
/// var area : i32 = compute_area(width, height); /// var area : i32 = compute_area(width, height);
@ -47,7 +47,7 @@ class Var final : public Castable<Var, Variable> {
/// @param source the variable source /// @param source the variable source
/// @param sym the variable symbol /// @param sym the variable symbol
/// @param type the declared variable type /// @param type the declared variable type
/// @param declared_storage_class the declared storage class /// @param declared_address_space the declared address space
/// @param declared_access the declared access control /// @param declared_access the declared access control
/// @param constructor the constructor expression /// @param constructor the constructor expression
/// @param attributes the variable attributes /// @param attributes the variable attributes
@ -56,7 +56,7 @@ class Var final : public Castable<Var, Variable> {
const Source& source, const Source& source,
const Symbol& sym, const Symbol& sym,
const ast::Type* type, const ast::Type* type,
StorageClass declared_storage_class, AddressSpace declared_address_space,
Access declared_access, Access declared_access,
const Expression* constructor, const Expression* constructor,
utils::VectorRef<const Attribute*> attributes); utils::VectorRef<const Attribute*> attributes);
@ -76,8 +76,8 @@ class Var final : public Castable<Var, Variable> {
/// @return the newly cloned node /// @return the newly cloned node
const Var* Clone(CloneContext* ctx) const override; const Var* Clone(CloneContext* ctx) const override;
/// The declared storage class /// The declared address space
const StorageClass declared_storage_class; const AddressSpace declared_address_space;
/// The declared access control /// The declared access control
const Access declared_access; const Access declared_access;

View File

@ -19,11 +19,11 @@
#include <vector> #include <vector>
#include "src/tint/ast/access.h" #include "src/tint/ast/access.h"
#include "src/tint/ast/address_space.h"
#include "src/tint/ast/attribute.h" #include "src/tint/ast/attribute.h"
#include "src/tint/ast/binding_attribute.h" #include "src/tint/ast/binding_attribute.h"
#include "src/tint/ast/expression.h" #include "src/tint/ast/expression.h"
#include "src/tint/ast/group_attribute.h" #include "src/tint/ast/group_attribute.h"
#include "src/tint/ast/storage_class.h"
// Forward declarations // Forward declarations
namespace tint::ast { namespace tint::ast {

View File

@ -25,10 +25,10 @@ namespace {
using VariableTest = TestHelper; using VariableTest = TestHelper;
TEST_F(VariableTest, Creation) { TEST_F(VariableTest, Creation) {
auto* v = Var("my_var", ty.i32(), StorageClass::kFunction); auto* v = Var("my_var", ty.i32(), AddressSpace::kFunction);
EXPECT_EQ(v->symbol, Symbol(1, ID())); EXPECT_EQ(v->symbol, Symbol(1, ID()));
EXPECT_EQ(v->declared_storage_class, StorageClass::kFunction); EXPECT_EQ(v->declared_address_space, AddressSpace::kFunction);
EXPECT_TRUE(v->type->Is<ast::I32>()); EXPECT_TRUE(v->type->Is<ast::I32>());
EXPECT_EQ(v->source.range.begin.line, 0u); EXPECT_EQ(v->source.range.begin.line, 0u);
EXPECT_EQ(v->source.range.begin.column, 0u); EXPECT_EQ(v->source.range.begin.column, 0u);
@ -38,10 +38,10 @@ TEST_F(VariableTest, Creation) {
TEST_F(VariableTest, CreationWithSource) { TEST_F(VariableTest, CreationWithSource) {
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}}, "i", auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}}, "i",
ty.f32(), StorageClass::kPrivate, utils::Empty); ty.f32(), AddressSpace::kPrivate, utils::Empty);
EXPECT_EQ(v->symbol, Symbol(1, ID())); EXPECT_EQ(v->symbol, Symbol(1, ID()));
EXPECT_EQ(v->declared_storage_class, StorageClass::kPrivate); EXPECT_EQ(v->declared_address_space, AddressSpace::kPrivate);
EXPECT_TRUE(v->type->Is<ast::F32>()); EXPECT_TRUE(v->type->Is<ast::F32>());
EXPECT_EQ(v->source.range.begin.line, 27u); EXPECT_EQ(v->source.range.begin.line, 27u);
EXPECT_EQ(v->source.range.begin.column, 4u); EXPECT_EQ(v->source.range.begin.column, 4u);
@ -51,10 +51,10 @@ TEST_F(VariableTest, CreationWithSource) {
TEST_F(VariableTest, CreationEmpty) { TEST_F(VariableTest, CreationEmpty) {
auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}}, "a_var", auto* v = Var(Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}}, "a_var",
ty.i32(), StorageClass::kWorkgroup, utils::Empty); ty.i32(), AddressSpace::kWorkgroup, utils::Empty);
EXPECT_EQ(v->symbol, Symbol(1, ID())); EXPECT_EQ(v->symbol, Symbol(1, ID()));
EXPECT_EQ(v->declared_storage_class, StorageClass::kWorkgroup); EXPECT_EQ(v->declared_address_space, AddressSpace::kWorkgroup);
EXPECT_TRUE(v->type->Is<ast::I32>()); EXPECT_TRUE(v->type->Is<ast::I32>());
EXPECT_EQ(v->source.range.begin.line, 27u); EXPECT_EQ(v->source.range.begin.line, 27u);
EXPECT_EQ(v->source.range.begin.column, 4u); EXPECT_EQ(v->source.range.begin.column, 4u);
@ -92,7 +92,7 @@ TEST_F(VariableTest, Assert_DifferentProgramID_Constructor) {
} }
TEST_F(VariableTest, WithAttributes) { TEST_F(VariableTest, WithAttributes) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, Location(1_u), auto* var = Var("my_var", ty.i32(), AddressSpace::kFunction, Location(1_u),
Builtin(BuiltinValue::kPosition), Id(1200_u)); Builtin(BuiltinValue::kPosition), Id(1200_u));
auto& attributes = var->attributes; auto& attributes = var->attributes;
@ -107,22 +107,22 @@ TEST_F(VariableTest, WithAttributes) {
} }
TEST_F(VariableTest, HasBindingPoint_BothProvided) { TEST_F(VariableTest, HasBindingPoint_BothProvided) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, Binding(2_a), Group(1_a)); auto* var = Var("my_var", ty.i32(), AddressSpace::kFunction, Binding(2_a), Group(1_a));
EXPECT_TRUE(var->HasBindingPoint()); EXPECT_TRUE(var->HasBindingPoint());
} }
TEST_F(VariableTest, HasBindingPoint_NeitherProvided) { TEST_F(VariableTest, HasBindingPoint_NeitherProvided) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, utils::Empty); auto* var = Var("my_var", ty.i32(), AddressSpace::kFunction, utils::Empty);
EXPECT_FALSE(var->HasBindingPoint()); EXPECT_FALSE(var->HasBindingPoint());
} }
TEST_F(VariableTest, HasBindingPoint_MissingGroupAttribute) { TEST_F(VariableTest, HasBindingPoint_MissingGroupAttribute) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, Binding(2_a)); auto* var = Var("my_var", ty.i32(), AddressSpace::kFunction, Binding(2_a));
EXPECT_FALSE(var->HasBindingPoint()); EXPECT_FALSE(var->HasBindingPoint());
} }
TEST_F(VariableTest, HasBindingPoint_MissingBindingAttribute) { TEST_F(VariableTest, HasBindingPoint_MissingBindingAttribute) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, Group(1_a)); auto* var = Var("my_var", ty.i32(), AddressSpace::kFunction, Group(1_a));
EXPECT_FALSE(var->HasBindingPoint()); EXPECT_FALSE(var->HasBindingPoint());
} }

View File

@ -272,7 +272,7 @@ fn f(b: i32) {
TEST(ReplaceIdentifierTest, NotApplicable5) { TEST(ReplaceIdentifierTest, NotApplicable5) {
// Can't replace `a` with `b` since the latter has a wrong access mode // Can't replace `a` with `b` since the latter has a wrong access mode
// (`read` for uniform storage class). // (`read` for uniform address space).
std::string shader = R"( std::string shader = R"(
struct S { struct S {
a: i32 a: i32
@ -343,7 +343,7 @@ fn f() {
TEST(ReplaceIdentifierTest, NotApplicable8) { TEST(ReplaceIdentifierTest, NotApplicable8) {
// Can't replace `ptr_b` with `c` since the latter has a wrong access mode and // Can't replace `ptr_b` with `c` since the latter has a wrong access mode and
// storage class. // address space.
std::string shader = R"( std::string shader = R"(
struct S { struct S {
a: i32 a: i32
@ -451,7 +451,7 @@ fn f() {
} }
TEST(ReplaceIdentifierTest, Applicable1) { TEST(ReplaceIdentifierTest, Applicable1) {
// Can replace `a` with `b` (same storage class). // Can replace `a` with `b` (same address space).
std::string shader = R"( std::string shader = R"(
fn f() { fn f() {
var b : vec2<u32>; var b : vec2<u32>;
@ -611,7 +611,7 @@ fn f() {
TEST(ReplaceIdentifierTest, NotApplicable14) { TEST(ReplaceIdentifierTest, NotApplicable14) {
// Can't replace `ptr_a` with `ptr_b` (both are pointers with different // Can't replace `ptr_a` with `ptr_b` (both are pointers with different
// storage class). // address space).
std::string shader = R"( std::string shader = R"(
var<private> b: vec2<u32>; var<private> b: vec2<u32>;
fn f() { fn f() {

View File

@ -565,7 +565,7 @@ uint32_t Inspector::GetWorkgroupStorageSize(const std::string& entry_point) {
uint32_t total_size = 0; uint32_t total_size = 0;
auto* func_sem = program_->Sem().Get(func); auto* func_sem = program_->Sem().Get(func);
for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) { for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) {
if (var->StorageClass() == ast::StorageClass::kWorkgroup) { if (var->AddressSpace() == ast::AddressSpace::kWorkgroup) {
auto* ty = var->Type()->UnwrapRef(); auto* ty = var->Type()->UnwrapRef();
uint32_t align = ty->Align(); uint32_t align = ty->Align();
uint32_t size = ty->Size(); uint32_t size = ty->Size();

View File

@ -126,11 +126,11 @@ void InspectorBuilder::AddUniformBuffer(const std::string& name,
const ast::Type* type, const ast::Type* type,
uint32_t group, uint32_t group,
uint32_t binding) { uint32_t binding) {
GlobalVar(name, type, ast::StorageClass::kUniform, Binding(AInt(binding)), Group(AInt(group))); GlobalVar(name, type, ast::AddressSpace::kUniform, Binding(AInt(binding)), Group(AInt(group)));
} }
void InspectorBuilder::AddWorkgroupStorage(const std::string& name, const ast::Type* type) { void InspectorBuilder::AddWorkgroupStorage(const std::string& name, const ast::Type* type) {
GlobalVar(name, type, ast::StorageClass::kWorkgroup); GlobalVar(name, type, ast::AddressSpace::kWorkgroup);
} }
void InspectorBuilder::AddStorageBuffer(const std::string& name, void InspectorBuilder::AddStorageBuffer(const std::string& name,
@ -138,7 +138,7 @@ void InspectorBuilder::AddStorageBuffer(const std::string& name,
ast::Access access, ast::Access access,
uint32_t group, uint32_t group,
uint32_t binding) { uint32_t binding) {
GlobalVar(name, type, ast::StorageClass::kStorage, access, Binding(AInt(binding)), GlobalVar(name, type, ast::AddressSpace::kStorage, access, Binding(AInt(binding)),
Group(AInt(group))); Group(AInt(group)));
} }
@ -188,7 +188,7 @@ void InspectorBuilder::AddResource(const std::string& name,
} }
void InspectorBuilder::AddGlobalVariable(const std::string& name, const ast::Type* type) { void InspectorBuilder::AddGlobalVariable(const std::string& name, const ast::Type* type) {
GlobalVar(name, type, ast::StorageClass::kPrivate); GlobalVar(name, type, ast::AddressSpace::kPrivate);
} }
const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction( const ast::Function* InspectorBuilder::MakeSamplerReferenceBodyFunction(

View File

@ -54,7 +54,7 @@ enum extension {
} }
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
enum storage_class { enum address_space {
@internal none @internal none
function function
private private
@ -125,7 +125,7 @@ type mat4x3<T>
type mat4x4<T> type mat4x4<T>
@display("vec{N}<{T}>") type vec<N: num, T> @display("vec{N}<{T}>") type vec<N: num, T>
@display("mat{N}x{M}<{T}>") type mat<N: num, M: num, T> @display("mat{N}x{M}<{T}>") type mat<N: num, M: num, T>
type ptr<S: storage_class, T, A: access> type ptr<S: address_space, T, A: access>
type atomic<T> type atomic<T>
type array<T> type array<T>
type sampler type sampler
@ -214,14 +214,14 @@ match write: access.write
match read_write: access.read_write match read_write: access.read_write
match function_private_workgroup match function_private_workgroup
: storage_class.function : address_space.function
| storage_class.private | address_space.private
| storage_class.workgroup | address_space.workgroup
match workgroup_or_storage match workgroup_or_storage
: storage_class.workgroup : address_space.workgroup
| storage_class.storage | address_space.storage
match storage match storage
: storage_class.storage : address_space.storage
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Builtin Functions // // Builtin Functions //

View File

@ -172,14 +172,14 @@ class ProgramBuilder {
~VarOptions(); ~VarOptions();
const ast::Type* type = nullptr; const ast::Type* type = nullptr;
ast::StorageClass storage = ast::StorageClass::kNone; ast::AddressSpace address_space = ast::AddressSpace::kNone;
ast::Access access = ast::Access::kUndefined; ast::Access access = ast::Access::kUndefined;
const ast::Expression* constructor = nullptr; const ast::Expression* constructor = nullptr;
utils::Vector<const ast::Attribute*, 4> attributes; utils::Vector<const ast::Attribute*, 4> attributes;
private: private:
void Set(const ast::Type* t) { type = t; } void Set(const ast::Type* t) { type = t; }
void Set(ast::StorageClass sc) { storage = sc; } void Set(ast::AddressSpace addr_space) { address_space = addr_space; }
void Set(ast::Access ac) { access = ac; } void Set(ast::Access ac) { access = ac; }
void Set(const ast::Expression* c) { constructor = c; } void Set(const ast::Expression* c) { constructor = c; }
void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); } void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
@ -902,45 +902,45 @@ class ProgramBuilder {
} }
/// @param type the type of the pointer /// @param type the type of the pointer
/// @param storage_class the storage class of the pointer /// @param address_space the address space of the pointer
/// @param access the optional access control of the pointer /// @param access the optional access control of the pointer
/// @return the pointer to `type` with the given ast::StorageClass /// @return the pointer to `type` with the given ast::AddressSpace
const ast::Pointer* pointer(const ast::Type* type, const ast::Pointer* pointer(const ast::Type* type,
ast::StorageClass storage_class, ast::AddressSpace address_space,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
return builder->create<ast::Pointer>(type, storage_class, access); return builder->create<ast::Pointer>(type, address_space, access);
} }
/// @param source the Source of the node /// @param source the Source of the node
/// @param type the type of the pointer /// @param type the type of the pointer
/// @param storage_class the storage class of the pointer /// @param address_space the address space of the pointer
/// @param access the optional access control of the pointer /// @param access the optional access control of the pointer
/// @return the pointer to `type` with the given ast::StorageClass /// @return the pointer to `type` with the given ast::AddressSpace
const ast::Pointer* pointer(const Source& source, const ast::Pointer* pointer(const Source& source,
const ast::Type* type, const ast::Type* type,
ast::StorageClass storage_class, ast::AddressSpace address_space,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
return builder->create<ast::Pointer>(source, type, storage_class, access); return builder->create<ast::Pointer>(source, type, address_space, access);
} }
/// @param storage_class the storage class of the pointer /// @param address_space the address space of the pointer
/// @param access the optional access control of the pointer /// @param access the optional access control of the pointer
/// @return the pointer to type `T` with the given ast::StorageClass. /// @return the pointer to type `T` with the given ast::AddressSpace.
template <typename T> template <typename T>
const ast::Pointer* pointer(ast::StorageClass storage_class, const ast::Pointer* pointer(ast::AddressSpace address_space,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
return pointer(Of<T>(), storage_class, access); return pointer(Of<T>(), address_space, access);
} }
/// @param source the Source of the node /// @param source the Source of the node
/// @param storage_class the storage class of the pointer /// @param address_space the address space of the pointer
/// @param access the optional access control of the pointer /// @param access the optional access control of the pointer
/// @return the pointer to type `T` with the given ast::StorageClass. /// @return the pointer to type `T` with the given ast::AddressSpace.
template <typename T> template <typename T>
const ast::Pointer* pointer(const Source& source, const ast::Pointer* pointer(const Source& source,
ast::StorageClass storage_class, ast::AddressSpace address_space,
ast::Access access = ast::Access::kUndefined) const { ast::Access access = ast::Access::kUndefined) const {
return pointer(source, Of<T>(), storage_class, access); return pointer(source, Of<T>(), address_space, access);
} }
/// @param source the Source of the node /// @param source the Source of the node
@ -1651,7 +1651,7 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor /// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order: /// Can be any of the following, in any order:
/// * ast::Type* - specifies the variable type /// * ast::Type* - specifies the variable type
/// * ast::StorageClass - specifies the variable storage class /// * ast::AddressSpace - specifies the variable address space
/// * ast::Access - specifies the variable's access control /// * ast::Access - specifies the variable's access control
/// * ast::Expression* - specifies the variable's initializer expression /// * ast::Expression* - specifies the variable's initializer expression
/// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
@ -1661,8 +1661,8 @@ class ProgramBuilder {
template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>> template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
const ast::Var* Var(NAME&& name, OPTIONS&&... options) { const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
VarOptions opts(std::forward<OPTIONS>(options)...); VarOptions opts(std::forward<OPTIONS>(options)...);
return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.storage, opts.access, return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.address_space,
opts.constructor, std::move(opts.attributes)); opts.access, opts.constructor, std::move(opts.attributes));
} }
/// @param source the variable source /// @param source the variable source
@ -1670,17 +1670,18 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor /// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order: /// Can be any of the following, in any order:
/// * ast::Type* - specifies the variable type /// * ast::Type* - specifies the variable type
/// * ast::StorageClass - specifies the variable storage class /// * ast::AddressSpace - specifies the variable address space
/// * ast::Access - specifies the variable's access control /// * ast::Access - specifies the variable's access control
/// * ast::Expression* - specifies the variable's initializer expression /// * ast::Expression* - specifies the variable's initializer expression
/// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
/// Note that non-repeatable arguments of the same type will use the last argument's value. /// Note that non-repeatable arguments of the same type will use the last argument's value.
/// @returns a `ast::Var` with the given name, storage and type /// @returns a `ast::Var` with the given name, address_space and type
template <typename NAME, typename... OPTIONS> template <typename NAME, typename... OPTIONS>
const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) { const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
VarOptions opts(std::forward<OPTIONS>(options)...); VarOptions opts(std::forward<OPTIONS>(options)...);
return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type, opts.storage, return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type,
opts.access, opts.constructor, std::move(opts.attributes)); opts.address_space, opts.access, opts.constructor,
std::move(opts.attributes));
} }
/// @param name the variable name /// @param name the variable name
@ -1773,7 +1774,7 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor /// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order: /// Can be any of the following, in any order:
/// * ast::Type* - specifies the variable type /// * ast::Type* - specifies the variable type
/// * ast::StorageClass - specifies the variable storage class /// * ast::AddressSpace - specifies the variable address space
/// * ast::Access - specifies the variable's access control /// * ast::Access - specifies the variable's access control
/// * ast::Expression* - specifies the variable's initializer expression /// * ast::Expression* - specifies the variable's initializer expression
/// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
@ -1792,7 +1793,7 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor /// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order: /// Can be any of the following, in any order:
/// * ast::Type* - specifies the variable type /// * ast::Type* - specifies the variable type
/// * ast::StorageClass - specifies the variable storage class /// * ast::AddressSpace - specifies the variable address space
/// * ast::Access - specifies the variable's access control /// * ast::Access - specifies the variable's access control
/// * ast::Expression* - specifies the variable's initializer expression /// * ast::Expression* - specifies the variable's initializer expression
/// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)

View File

@ -46,7 +46,7 @@ TEST_F(ProgramTest, IDsAreUnique) {
} }
TEST_F(ProgramTest, Assert_GlobalVariable) { TEST_F(ProgramTest, Assert_GlobalVariable) {
GlobalVar("var", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("var", ty.f32(), ast::AddressSpace::kPrivate);
Program program(std::move(*this)); Program program(std::move(*this));
EXPECT_TRUE(program.IsValid()); EXPECT_TRUE(program.IsValid());

View File

@ -36,30 +36,30 @@ ast::PipelineStage EnumConverter::ToPipelineStage(SpvExecutionModel model) {
return ast::PipelineStage::kNone; return ast::PipelineStage::kNone;
} }
ast::StorageClass EnumConverter::ToStorageClass(const SpvStorageClass sc) { ast::AddressSpace EnumConverter::ToAddressSpace(const SpvStorageClass sc) {
switch (sc) { switch (sc) {
case SpvStorageClassInput: case SpvStorageClassInput:
return ast::StorageClass::kIn; return ast::AddressSpace::kIn;
case SpvStorageClassOutput: case SpvStorageClassOutput:
return ast::StorageClass::kOut; return ast::AddressSpace::kOut;
case SpvStorageClassUniform: case SpvStorageClassUniform:
return ast::StorageClass::kUniform; return ast::AddressSpace::kUniform;
case SpvStorageClassWorkgroup: case SpvStorageClassWorkgroup:
return ast::StorageClass::kWorkgroup; return ast::AddressSpace::kWorkgroup;
case SpvStorageClassUniformConstant: case SpvStorageClassUniformConstant:
return ast::StorageClass::kNone; return ast::AddressSpace::kNone;
case SpvStorageClassStorageBuffer: case SpvStorageClassStorageBuffer:
return ast::StorageClass::kStorage; return ast::AddressSpace::kStorage;
case SpvStorageClassPrivate: case SpvStorageClassPrivate:
return ast::StorageClass::kPrivate; return ast::AddressSpace::kPrivate;
case SpvStorageClassFunction: case SpvStorageClassFunction:
return ast::StorageClass::kFunction; return ast::AddressSpace::kFunction;
default: default:
break; break;
} }
Fail() << "unknown SPIR-V storage class: " << uint32_t(sc); Fail() << "unknown SPIR-V storage class: " << uint32_t(sc);
return ast::StorageClass::kInvalid; return ast::AddressSpace::kInvalid;
} }
ast::BuiltinValue EnumConverter::ToBuiltin(SpvBuiltIn b) { ast::BuiltinValue EnumConverter::ToBuiltin(SpvBuiltIn b) {

View File

@ -16,9 +16,9 @@
#define SRC_TINT_READER_SPIRV_ENUM_CONVERTER_H_ #define SRC_TINT_READER_SPIRV_ENUM_CONVERTER_H_
#include "spirv/unified1/spirv.h" #include "spirv/unified1/spirv.h"
#include "src/tint/ast/address_space.h"
#include "src/tint/ast/builtin_value.h" #include "src/tint/ast/builtin_value.h"
#include "src/tint/ast/pipeline_stage.h" #include "src/tint/ast/pipeline_stage.h"
#include "src/tint/ast/storage_class.h"
#include "src/tint/reader/spirv/fail_stream.h" #include "src/tint/reader/spirv/fail_stream.h"
#include "src/tint/sem/storage_texture.h" #include "src/tint/sem/storage_texture.h"
@ -39,11 +39,11 @@ class EnumConverter {
/// @returns a Tint AST pipeline stage /// @returns a Tint AST pipeline stage
ast::PipelineStage ToPipelineStage(SpvExecutionModel model); ast::PipelineStage ToPipelineStage(SpvExecutionModel model);
/// Converts a SPIR-V storage class to a Tint storage class. /// Converts a SPIR-V storage class to a Tint address space.
/// On failure, logs an error and returns kNone /// On failure, logs an error and returns kNone
/// @param sc the SPIR-V storage class /// @param sc the SPIR-V storage class
/// @returns a Tint AST storage class /// @returns a Tint AST address space
ast::StorageClass ToStorageClass(const SpvStorageClass sc); ast::AddressSpace ToAddressSpace(const SpvStorageClass sc);
/// Converts a SPIR-V Builtin value a Tint Builtin. /// Converts a SPIR-V Builtin value a Tint Builtin.
/// On failure, logs an error and returns kNone /// On failure, logs an error and returns kNone

View File

@ -84,7 +84,7 @@ INSTANTIATE_TEST_SUITE_P(EnumConverterBad,
struct StorageClassCase { struct StorageClassCase {
SpvStorageClass sc; SpvStorageClass sc;
bool expect_success; bool expect_success;
ast::StorageClass expected; ast::AddressSpace expected;
}; };
inline std::ostream& operator<<(std::ostream& out, StorageClassCase scc) { inline std::ostream& operator<<(std::ostream& out, StorageClassCase scc) {
out << "StorageClassCase{ SpvStorageClass:" << int(scc.sc) out << "StorageClassCase{ SpvStorageClass:" << int(scc.sc)
@ -110,7 +110,7 @@ class SpvStorageClassTest : public testing::TestWithParam<StorageClassCase> {
TEST_P(SpvStorageClassTest, Samples) { TEST_P(SpvStorageClassTest, Samples) {
const auto params = GetParam(); const auto params = GetParam();
const auto result = converter_.ToStorageClass(params.sc); const auto result = converter_.ToAddressSpace(params.sc);
EXPECT_EQ(success_, params.expect_success); EXPECT_EQ(success_, params.expect_success);
if (params.expect_success) { if (params.expect_success) {
EXPECT_EQ(result, params.expected); EXPECT_EQ(result, params.expected);
@ -125,19 +125,19 @@ INSTANTIATE_TEST_SUITE_P(
EnumConverterGood, EnumConverterGood,
SpvStorageClassTest, SpvStorageClassTest,
testing::Values( testing::Values(
StorageClassCase{SpvStorageClassInput, true, ast::StorageClass::kIn}, StorageClassCase{SpvStorageClassInput, true, ast::AddressSpace::kIn},
StorageClassCase{SpvStorageClassOutput, true, ast::StorageClass::kOut}, StorageClassCase{SpvStorageClassOutput, true, ast::AddressSpace::kOut},
StorageClassCase{SpvStorageClassUniform, true, ast::StorageClass::kUniform}, StorageClassCase{SpvStorageClassUniform, true, ast::AddressSpace::kUniform},
StorageClassCase{SpvStorageClassWorkgroup, true, ast::StorageClass::kWorkgroup}, StorageClassCase{SpvStorageClassWorkgroup, true, ast::AddressSpace::kWorkgroup},
StorageClassCase{SpvStorageClassUniformConstant, true, ast::StorageClass::kNone}, StorageClassCase{SpvStorageClassUniformConstant, true, ast::AddressSpace::kNone},
StorageClassCase{SpvStorageClassStorageBuffer, true, ast::StorageClass::kStorage}, StorageClassCase{SpvStorageClassStorageBuffer, true, ast::AddressSpace::kStorage},
StorageClassCase{SpvStorageClassPrivate, true, ast::StorageClass::kPrivate}, StorageClassCase{SpvStorageClassPrivate, true, ast::AddressSpace::kPrivate},
StorageClassCase{SpvStorageClassFunction, true, ast::StorageClass::kFunction})); StorageClassCase{SpvStorageClassFunction, true, ast::AddressSpace::kFunction}));
INSTANTIATE_TEST_SUITE_P(EnumConverterBad, INSTANTIATE_TEST_SUITE_P(EnumConverterBad,
SpvStorageClassTest, SpvStorageClassTest,
testing::Values(StorageClassCase{static_cast<SpvStorageClass>(9999), false, testing::Values(StorageClassCase{static_cast<SpvStorageClass>(9999), false,
ast::StorageClass::kInvalid})); ast::AddressSpace::kInvalid}));
// Builtin // Builtin

View File

@ -2500,11 +2500,11 @@ bool FunctionEmitter::EmitFunctionVariables() {
return false; return false;
} }
} }
auto* var = parser_impl_.MakeVar(inst.result_id(), ast::StorageClass::kNone, var_store_type, auto* var = parser_impl_.MakeVar(inst.result_id(), ast::AddressSpace::kNone, var_store_type,
constructor, AttributeList{}); constructor, AttributeList{});
auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var); auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var);
AddStatement(var_decl_stmt); AddStatement(var_decl_stmt);
auto* var_type = ty_.Reference(var_store_type, ast::StorageClass::kNone); auto* var_type = ty_.Reference(var_store_type, ast::AddressSpace::kNone);
identifier_types_.emplace(inst.result_id(), var_type); identifier_types_.emplace(inst.result_id(), var_type);
} }
return success(); return success();
@ -3356,11 +3356,11 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
for (auto id : sorted_by_index(block_info.hoisted_ids)) { for (auto id : sorted_by_index(block_info.hoisted_ids)) {
const auto* def_inst = def_use_mgr_->GetDef(id); const auto* def_inst = def_use_mgr_->GetDef(id);
TINT_ASSERT(Reader, def_inst); TINT_ASSERT(Reader, def_inst);
auto* storage_type = RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id); auto* storage_type = RemapAddressSpace(parser_impl_.ConvertType(def_inst->type_id()), id);
AddStatement(create<ast::VariableDeclStatement>( AddStatement(create<ast::VariableDeclStatement>(
Source{}, parser_impl_.MakeVar(id, ast::StorageClass::kNone, storage_type, nullptr, Source{}, parser_impl_.MakeVar(id, ast::AddressSpace::kNone, storage_type, nullptr,
AttributeList{}))); AttributeList{})));
auto* type = ty_.Reference(storage_type, ast::StorageClass::kNone); auto* type = ty_.Reference(storage_type, ast::AddressSpace::kNone);
identifier_types_.emplace(id, type); identifier_types_.emplace(id, type);
} }
@ -3720,7 +3720,7 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
if (!expr) { if (!expr) {
return false; return false;
} }
expr.type = RemapStorageClass(expr.type, result_id); expr.type = RemapAddressSpace(expr.type, result_id);
return EmitConstDefOrWriteToHoistedVar(inst, expr); return EmitConstDefOrWriteToHoistedVar(inst, expr);
} }
@ -3777,15 +3777,15 @@ TypedExpression FunctionEmitter::MakeOperand(const spvtools::opt::Instruction& i
return parser_impl_.RectifyOperandSignedness(inst, std::move(expr)); return parser_impl_.RectifyOperandSignedness(inst, std::move(expr));
} }
TypedExpression FunctionEmitter::InferFunctionStorageClass(TypedExpression expr) { TypedExpression FunctionEmitter::InferFunctionAddressSpace(TypedExpression expr) {
TypedExpression result(expr); TypedExpression result(expr);
if (const auto* ref = expr.type->UnwrapAlias()->As<Reference>()) { if (const auto* ref = expr.type->UnwrapAlias()->As<Reference>()) {
if (ref->storage_class == ast::StorageClass::kNone) { if (ref->address_space == ast::AddressSpace::kNone) {
expr.type = ty_.Reference(ref->type, ast::StorageClass::kFunction); expr.type = ty_.Reference(ref->type, ast::AddressSpace::kFunction);
} }
} else if (const auto* ptr = expr.type->UnwrapAlias()->As<Pointer>()) { } else if (const auto* ptr = expr.type->UnwrapAlias()->As<Pointer>()) {
if (ptr->storage_class == ast::StorageClass::kNone) { if (ptr->address_space == ast::AddressSpace::kNone) {
expr.type = ty_.Pointer(ptr->type, ast::StorageClass::kFunction); expr.type = ty_.Pointer(ptr->type, ast::AddressSpace::kFunction);
} }
} }
return expr; return expr;
@ -4418,7 +4418,7 @@ TypedExpression FunctionEmitter::MakeAccessChain(const spvtools::opt::Instructio
// ever-deeper nested indexing expressions. Start off with an expression // ever-deeper nested indexing expressions. Start off with an expression
// for the base, and then bury that inside nested indexing expressions. // for the base, and then bury that inside nested indexing expressions.
if (!current_expr) { if (!current_expr) {
current_expr = InferFunctionStorageClass(MakeOperand(inst, 0)); current_expr = InferFunctionAddressSpace(MakeOperand(inst, 0));
if (current_expr.type->Is<Pointer>()) { if (current_expr.type->Is<Pointer>()) {
current_expr = Dereference(current_expr); current_expr = Dereference(current_expr);
} }
@ -4430,7 +4430,7 @@ TypedExpression FunctionEmitter::MakeAccessChain(const spvtools::opt::Instructio
Fail() << "Access chain %" << inst.result_id() << " base pointer is not of pointer type"; Fail() << "Access chain %" << inst.result_id() << " base pointer is not of pointer type";
return {}; return {};
} }
SpvStorageClass storage_class = SpvStorageClass address_space =
static_cast<SpvStorageClass>(ptr_type_inst->GetSingleWordInOperand(0)); static_cast<SpvStorageClass>(ptr_type_inst->GetSingleWordInOperand(0));
uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1); uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
@ -4521,7 +4521,7 @@ TypedExpression FunctionEmitter::MakeAccessChain(const spvtools::opt::Instructio
<< ": " << pointee_type_inst->PrettyPrint(); << ": " << pointee_type_inst->PrettyPrint();
return {}; return {};
} }
const auto pointer_type_id = type_mgr_->FindPointerToType(pointee_type_id, storage_class); const auto pointer_type_id = type_mgr_->FindPointerToType(pointee_type_id, address_space);
auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref); auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref);
TINT_ASSERT(Reader, type && type->Is<Reference>()); TINT_ASSERT(Reader, type && type->Is<Reference>());
current_expr = TypedExpression{type, next_expr}; current_expr = TypedExpression{type, next_expr};
@ -4799,8 +4799,8 @@ bool FunctionEmitter::RegisterLocallyDefinedValues() {
++index; ++index;
auto& info = def_info_[result_id]; auto& info = def_info_[result_id];
// Determine storage class for pointer values. Do this in order because // Determine address space for pointer values. Do this in order because
// we might rely on the storage class for a previously-visited definition. // we might rely on the address space for a previously-visited definition.
// Logical pointers can't be transmitted through OpPhi, so remaining // Logical pointers can't be transmitted through OpPhi, so remaining
// pointer definitions are SSA values, and their definitions must be // pointer definitions are SSA values, and their definitions must be
// visited before their uses. // visited before their uses.
@ -4809,7 +4809,7 @@ bool FunctionEmitter::RegisterLocallyDefinedValues() {
if (type->AsPointer()) { if (type->AsPointer()) {
if (auto* ast_type = parser_impl_.ConvertType(inst.type_id())) { if (auto* ast_type = parser_impl_.ConvertType(inst.type_id())) {
if (auto* ptr = ast_type->As<Pointer>()) { if (auto* ptr = ast_type->As<Pointer>()) {
info->storage_class = ptr->storage_class; info->address_space = ptr->address_space;
} }
} }
switch (inst.opcode()) { switch (inst.opcode()) {
@ -4823,8 +4823,8 @@ bool FunctionEmitter::RegisterLocallyDefinedValues() {
case SpvOpCopyObject: case SpvOpCopyObject:
// Inherit from the first operand. We need this so we can pick up // Inherit from the first operand. We need this so we can pick up
// a remapped storage buffer. // a remapped storage buffer.
info->storage_class = info->address_space =
GetStorageClassForPointerValue(inst.GetSingleWordInOperand(0)); GetAddressSpaceForPointerValue(inst.GetSingleWordInOperand(0));
break; break;
default: default:
return Fail() << "pointer defined in function from unknown opcode: " return Fail() << "pointer defined in function from unknown opcode: "
@ -4846,11 +4846,11 @@ bool FunctionEmitter::RegisterLocallyDefinedValues() {
return true; return true;
} }
ast::StorageClass FunctionEmitter::GetStorageClassForPointerValue(uint32_t id) { ast::AddressSpace FunctionEmitter::GetAddressSpaceForPointerValue(uint32_t id) {
auto where = def_info_.find(id); auto where = def_info_.find(id);
if (where != def_info_.end()) { if (where != def_info_.end()) {
auto candidate = where->second.get()->storage_class; auto candidate = where->second.get()->address_space;
if (candidate != ast::StorageClass::kInvalid) { if (candidate != ast::AddressSpace::kInvalid) {
return candidate; return candidate;
} }
} }
@ -4858,19 +4858,19 @@ ast::StorageClass FunctionEmitter::GetStorageClassForPointerValue(uint32_t id) {
if (type_id) { if (type_id) {
auto* ast_type = parser_impl_.ConvertType(type_id); auto* ast_type = parser_impl_.ConvertType(type_id);
if (auto* ptr = As<Pointer>(ast_type)) { if (auto* ptr = As<Pointer>(ast_type)) {
return ptr->storage_class; return ptr->address_space;
} }
} }
return ast::StorageClass::kInvalid; return ast::AddressSpace::kInvalid;
} }
const Type* FunctionEmitter::RemapStorageClass(const Type* type, uint32_t result_id) { const Type* FunctionEmitter::RemapAddressSpace(const Type* type, uint32_t result_id) {
if (auto* ast_ptr_type = As<Pointer>(type)) { if (auto* ast_ptr_type = As<Pointer>(type)) {
// Remap an old-style storage buffer pointer to a new-style storage // Remap an old-style storage buffer pointer to a new-style storage
// buffer pointer. // buffer pointer.
const auto sc = GetStorageClassForPointerValue(result_id); const auto addr_space = GetAddressSpaceForPointerValue(result_id);
if (ast_ptr_type->storage_class != sc) { if (ast_ptr_type->address_space != addr_space) {
return ty_.Pointer(ast_ptr_type->type, sc); return ty_.Pointer(ast_ptr_type->type, addr_space);
} }
} }
return type; return type;
@ -5053,7 +5053,7 @@ void FunctionEmitter::FindValuesNeedingNamedOrHoistedDefinition() {
// Avoid moving combinatorial values across constructs. This is a // Avoid moving combinatorial values across constructs. This is a
// simple heuristic to avoid changing the cost of an operation // simple heuristic to avoid changing the cost of an operation
// by moving it into or out of a loop, for example. // by moving it into or out of a loop, for example.
if ((def_info->storage_class == ast::StorageClass::kInvalid) && if ((def_info->address_space == ast::AddressSpace::kInvalid) &&
local_def.used_in_another_construct) { local_def.used_in_another_construct) {
should_hoist_to_let = true; should_hoist_to_let = true;
} }
@ -6170,7 +6170,7 @@ bool FunctionEmitter::MakeVectorInsertDynamic(const spvtools::opt::Instruction&
// API in parser_impl_. // API in parser_impl_.
var_name = namer_.MakeDerivedName(original_value_name); var_name = namer_.MakeDerivedName(original_value_name);
auto* temp_var = builder_.Var(var_name, type->Build(builder_), ast::StorageClass::kNone, auto* temp_var = builder_.Var(var_name, type->Build(builder_), ast::AddressSpace::kNone,
src_vector.expr); src_vector.expr);
AddStatement(builder_.Decl({}, temp_var)); AddStatement(builder_.Decl({}, temp_var));
@ -6240,7 +6240,7 @@ bool FunctionEmitter::MakeCompositeInsert(const spvtools::opt::Instruction& inst
// It doesn't correspond to a SPIR-V ID, so we don't use the ordinary // It doesn't correspond to a SPIR-V ID, so we don't use the ordinary
// API in parser_impl_. // API in parser_impl_.
var_name = namer_.MakeDerivedName(original_value_name); var_name = namer_.MakeDerivedName(original_value_name);
auto* temp_var = builder_.Var(var_name, type->Build(builder_), ast::StorageClass::kNone, auto* temp_var = builder_.Var(var_name, type->Build(builder_), ast::AddressSpace::kNone,
src_composite.expr); src_composite.expr);
AddStatement(builder_.Decl({}, temp_var)); AddStatement(builder_.Decl({}, temp_var));
} }
@ -6271,7 +6271,7 @@ TypedExpression FunctionEmitter::AddressOf(TypedExpression expr) {
return {}; return {};
} }
return { return {
ty_.Pointer(ref->type, ref->storage_class), ty_.Pointer(ref->type, ref->address_space),
create<ast::UnaryOpExpression>(Source{}, ast::UnaryOp::kAddressOf, expr.expr), create<ast::UnaryOpExpression>(Source{}, ast::UnaryOp::kAddressOf, expr.expr),
}; };
} }

View File

@ -325,12 +325,12 @@ struct DefInfo {
/// example, pointers. crbug.com/tint/98 /// example, pointers. crbug.com/tint/98
bool requires_hoisted_var_def = false; bool requires_hoisted_var_def = false;
/// The storage class to use for this value, if it is of pointer type. /// The address space to use for this value, if it is of pointer type.
/// This is required to carry a storage class override from a storage /// This is required to carry an address space override from a storage
/// buffer expressed in the old style (with Uniform storage class) /// buffer expressed in the old style (with Uniform address space)
/// that needs to be remapped to StorageBuffer storage class. /// that needs to be remapped to StorageBuffer address space.
/// This is kInvalid for non-pointers. /// This is kInvalid for non-pointers.
ast::StorageClass storage_class = ast::StorageClass::kInvalid; ast::AddressSpace address_space = ast::AddressSpace::kInvalid;
/// The expression to use when sinking pointers into their use. /// The expression to use when sinking pointers into their use.
/// When encountering a use of this instruction, we will emit this expression /// When encountering a use of this instruction, we will emit this expression
@ -360,8 +360,8 @@ inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) {
} }
o << " requires_named_let_def: " << (di.requires_named_let_def ? "true" : "false") o << " requires_named_let_def: " << (di.requires_named_let_def ? "true" : "false")
<< " requires_hoisted_var_def: " << (di.requires_hoisted_var_def ? "true" : "false"); << " requires_hoisted_var_def: " << (di.requires_hoisted_var_def ? "true" : "false");
if (di.storage_class != ast::StorageClass::kNone) { if (di.address_space != ast::AddressSpace::kNone) {
o << " sc:" << int(di.storage_class); o << " sc:" << int(di.address_space);
} }
switch (di.skip) { switch (di.skip) {
case SkipReason::kDontSkip: case SkipReason::kDontSkip:
@ -470,7 +470,7 @@ class FunctionEmitter {
/// by the `index_prefix`, which successively indexes into the variable. /// by the `index_prefix`, which successively indexes into the variable.
/// Also generates the assignment statements that copy the input parameter /// Also generates the assignment statements that copy the input parameter
/// to the corresponding part of the variable. Assumes the variable /// to the corresponding part of the variable. Assumes the variable
/// has already been created in the Private storage class. /// has already been created in the Private address space.
/// @param var_name The name of the variable /// @param var_name The name of the variable
/// @param var_type The store type of the variable /// @param var_type The store type of the variable
/// @param decos The variable's decorations /// @param decos The variable's decorations
@ -496,8 +496,7 @@ class FunctionEmitter {
/// expressions that compute the value they contribute to the entry point /// expressions that compute the value they contribute to the entry point
/// return value. The part of the output variable is specfied /// return value. The part of the output variable is specfied
/// by the `index_prefix`, which successively indexes into the variable. /// by the `index_prefix`, which successively indexes into the variable.
/// Assumes the variable has already been created in the Private storage /// Assumes the variable has already been created in the Private address space
/// class.
/// @param var_name The name of the variable /// @param var_name The name of the variable
/// @param var_type The store type of the variable /// @param var_type The store type of the variable
/// @param decos The variable's decorations /// @param decos The variable's decorations
@ -612,19 +611,19 @@ class FunctionEmitter {
/// @returns false on failure /// @returns false on failure
bool RegisterLocallyDefinedValues(); bool RegisterLocallyDefinedValues();
/// Returns the Tint storage class for the given SPIR-V ID that is a /// Returns the Tint address space for the given SPIR-V ID that is a
/// pointer value. /// pointer value.
/// @param id a SPIR-V ID for a pointer value /// @param id a SPIR-V ID for a pointer value
/// @returns the storage class /// @returns the address space
ast::StorageClass GetStorageClassForPointerValue(uint32_t id); ast::AddressSpace GetAddressSpaceForPointerValue(uint32_t id);
/// Remaps the storage class for the type of a locally-defined value, /// Remaps the address space for the type of a locally-defined value,
/// if necessary. If it's not a pointer type, or if its storage class /// if necessary. If it's not a pointer type, or if its address space
/// already matches, then the result is a copy of the `type` argument. /// already matches, then the result is a copy of the `type` argument.
/// @param type the AST type /// @param type the AST type
/// @param result_id the SPIR-V ID for the locally defined value /// @param result_id the SPIR-V ID for the locally defined value
/// @returns an possibly updated type /// @returns an possibly updated type
const Type* RemapStorageClass(const Type* type, uint32_t result_id); const Type* RemapAddressSpace(const Type* type, uint32_t result_id);
/// Marks locally defined values when they should get a 'let' /// Marks locally defined values when they should get a 'let'
/// definition in WGSL, or a 'var' definition at an outer scope. /// definition in WGSL, or a 'var' definition at an outer scope.
@ -1005,11 +1004,11 @@ class FunctionEmitter {
TypedExpression MakeOperand(const spvtools::opt::Instruction& inst, uint32_t operand_index); TypedExpression MakeOperand(const spvtools::opt::Instruction& inst, uint32_t operand_index);
/// Copies a typed expression to the result, but when the type is a pointer /// Copies a typed expression to the result, but when the type is a pointer
/// or reference type, ensures the storage class is not defaulted. That is, /// or reference type, ensures the address space is not defaulted. That is,
/// it changes a storage class of "none" to "function". /// it changes a address space of "none" to "function".
/// @param expr a typed expression /// @param expr a typed expression
/// @results a copy of the expression, with possibly updated type /// @results a copy of the expression, with possibly updated type
TypedExpression InferFunctionStorageClass(TypedExpression expr); TypedExpression InferFunctionAddressSpace(TypedExpression expr);
/// Returns an expression for a SPIR-V OpFMod instruction. /// Returns an expression for a SPIR-V OpFMod instruction.
/// @param inst the SPIR-V instruction /// @param inst the SPIR-V instruction

View File

@ -818,11 +818,11 @@ fn main() {
EXPECT_EQ(got, expected) << got; EXPECT_EQ(got, expected) << got;
} }
TEST_F(SpvParserMemoryTest, EmitStatement_AccessChain_InferFunctionStorageClass) { TEST_F(SpvParserMemoryTest, EmitStatement_AccessChain_InferFunctionAddressSpace) {
// An access chain can have no indices. When the base is a Function variable, // An access chain can have no indices. When the base is a Function variable,
// the reference type has no explicit storage class in the AST representation. // the reference type has no explicit address space in the AST representation.
// But the pointer type for the let declaration must have an explicit // But the pointer type for the let declaration must have an explicit
// 'function' storage class. From crbug.com/tint/807 // 'function' address space. From crbug.com/tint/807
const std::string assembly = R"( const std::string assembly = R"(
OpCapability Shader OpCapability Shader
OpMemoryModel Logical Simple OpMemoryModel Logical Simple
@ -993,7 +993,7 @@ TEST_F(SpvParserMemoryTest, RemapStorageBuffer_ThroughAccessChain_Cascaded) {
TEST_F(SpvParserMemoryTest, RemapStorageBuffer_ThroughCopyObject_WithoutHoisting) { TEST_F(SpvParserMemoryTest, RemapStorageBuffer_ThroughCopyObject_WithoutHoisting) {
// Generates a const declaration directly. // Generates a const declaration directly.
// We have to do a bunch of storage class tracking for locally // We have to do a bunch of address space tracking for locally
// defined values in order to get the right pointer-to-storage-buffer // defined values in order to get the right pointer-to-storage-buffer
// value type for the const declration. // value type for the const declration.
const auto assembly = OldStorageBufferPreamble() + R"( const auto assembly = OldStorageBufferPreamble() + R"(

View File

@ -1205,28 +1205,28 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
return nullptr; return nullptr;
} }
auto ast_storage_class = enum_converter_.ToStorageClass(storage_class); auto ast_address_space = enum_converter_.ToAddressSpace(storage_class);
if (ast_storage_class == ast::StorageClass::kInvalid) { if (ast_address_space == ast::AddressSpace::kInvalid) {
Fail() << "SPIR-V pointer type with ID " << type_id << " has invalid storage class " Fail() << "SPIR-V pointer type with ID " << type_id << " has invalid storage class "
<< static_cast<uint32_t>(storage_class); << static_cast<uint32_t>(storage_class);
return nullptr; return nullptr;
} }
if (ast_storage_class == ast::StorageClass::kUniform && if (ast_address_space == ast::AddressSpace::kUniform &&
remap_buffer_block_type_.count(pointee_type_id)) { remap_buffer_block_type_.count(pointee_type_id)) {
ast_storage_class = ast::StorageClass::kStorage; ast_address_space = ast::AddressSpace::kStorage;
remap_buffer_block_type_.insert(type_id); remap_buffer_block_type_.insert(type_id);
} }
// Pipeline input and output variables map to private variables. // Pipeline input and output variables map to private variables.
if (ast_storage_class == ast::StorageClass::kIn || if (ast_address_space == ast::AddressSpace::kIn ||
ast_storage_class == ast::StorageClass::kOut) { ast_address_space == ast::AddressSpace::kOut) {
ast_storage_class = ast::StorageClass::kPrivate; ast_address_space = ast::AddressSpace::kPrivate;
} }
switch (ptr_as) { switch (ptr_as) {
case PtrAs::Ref: case PtrAs::Ref:
return ty_.Reference(ast_elem_ty, ast_storage_class); return ty_.Reference(ast_elem_ty, ast_address_space);
case PtrAs::Ptr: case PtrAs::Ptr:
return ty_.Pointer(ast_elem_ty, ast_storage_class); return ty_.Pointer(ast_elem_ty, ast_address_space);
} }
Fail() << "invalid value for ptr_as: " << static_cast<int>(ptr_as); Fail() << "invalid value for ptr_as: " << static_cast<int>(ptr_as);
return nullptr; return nullptr;
@ -1443,15 +1443,15 @@ bool ParserImpl::EmitModuleScopeVariables() {
var.NumInOperands() > 1 ? var.GetSingleWordInOperand(1) : 0u; var.NumInOperands() > 1 ? var.GetSingleWordInOperand(1) : 0u;
continue; continue;
} }
switch (enum_converter_.ToStorageClass(spirv_storage_class)) { switch (enum_converter_.ToAddressSpace(spirv_storage_class)) {
case ast::StorageClass::kNone: case ast::AddressSpace::kNone:
case ast::StorageClass::kIn: case ast::AddressSpace::kIn:
case ast::StorageClass::kOut: case ast::AddressSpace::kOut:
case ast::StorageClass::kUniform: case ast::AddressSpace::kUniform:
case ast::StorageClass::kHandle: case ast::AddressSpace::kHandle:
case ast::StorageClass::kStorage: case ast::AddressSpace::kStorage:
case ast::StorageClass::kWorkgroup: case ast::AddressSpace::kWorkgroup:
case ast::StorageClass::kPrivate: case ast::AddressSpace::kPrivate:
break; break;
default: default:
return Fail() << "invalid SPIR-V storage class " << int(spirv_storage_class) return Fail() << "invalid SPIR-V storage class " << int(spirv_storage_class)
@ -1481,7 +1481,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
} }
auto* ast_store_type = ast_type->As<Pointer>()->type; auto* ast_store_type = ast_type->As<Pointer>()->type;
auto ast_storage_class = ast_type->As<Pointer>()->storage_class; auto ast_address_space = ast_type->As<Pointer>()->address_space;
const ast::Expression* ast_constructor = nullptr; const ast::Expression* ast_constructor = nullptr;
if (var.NumInOperands() > 1) { if (var.NumInOperands() > 1) {
// SPIR-V initializers are always constants. // SPIR-V initializers are always constants.
@ -1489,7 +1489,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
// here.) // here.)
ast_constructor = MakeConstantExpression(var.GetSingleWordInOperand(1)).expr; ast_constructor = MakeConstantExpression(var.GetSingleWordInOperand(1)).expr;
} }
auto* ast_var = MakeVar(var.result_id(), ast_storage_class, ast_store_type, ast_constructor, auto* ast_var = MakeVar(var.result_id(), ast_address_space, ast_store_type, ast_constructor,
utils::Empty); utils::Empty);
// TODO(dneto): initializers (a.k.a. constructor expression) // TODO(dneto): initializers (a.k.a. constructor expression)
if (ast_var) { if (ast_var) {
@ -1522,7 +1522,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
} }
auto* ast_var = auto* ast_var =
MakeVar(builtin_position_.per_vertex_var_id, MakeVar(builtin_position_.per_vertex_var_id,
enum_converter_.ToStorageClass(builtin_position_.storage_class), enum_converter_.ToAddressSpace(builtin_position_.storage_class),
ConvertType(builtin_position_.position_member_type_id), ast_constructor, {}); ConvertType(builtin_position_.position_member_type_id), ast_constructor, {});
builder_.AST().AddGlobalVariable(ast_var); builder_.AST().AddGlobalVariable(ast_var);
@ -1554,7 +1554,7 @@ const spvtools::opt::analysis::IntConstant* ParserImpl::GetArraySize(uint32_t va
} }
ast::Var* ParserImpl::MakeVar(uint32_t id, ast::Var* ParserImpl::MakeVar(uint32_t id,
ast::StorageClass sc, ast::AddressSpace address_space,
const Type* storage_type, const Type* storage_type,
const ast::Expression* constructor, const ast::Expression* constructor,
AttributeList decorations) { AttributeList decorations) {
@ -1564,7 +1564,7 @@ ast::Var* ParserImpl::MakeVar(uint32_t id,
} }
ast::Access access = ast::Access::kUndefined; ast::Access access = ast::Access::kUndefined;
if (sc == ast::StorageClass::kStorage) { if (address_space == ast::AddressSpace::kStorage) {
bool read_only = false; bool read_only = false;
if (auto* tn = storage_type->As<Named>()) { if (auto* tn = storage_type->As<Named>()) {
read_only = read_only_struct_types_.count(tn->name) > 0; read_only = read_only_struct_types_.count(tn->name) > 0;
@ -1575,19 +1575,19 @@ ast::Var* ParserImpl::MakeVar(uint32_t id,
} }
// Handle variables (textures and samplers) are always in the handle // Handle variables (textures and samplers) are always in the handle
// storage class, so we don't mention the storage class. // address space, so we don't mention the address space.
if (sc == ast::StorageClass::kHandle) { if (address_space == ast::AddressSpace::kHandle) {
sc = ast::StorageClass::kNone; address_space = ast::AddressSpace::kNone;
} }
if (!ConvertDecorationsForVariable(id, &storage_type, &decorations, if (!ConvertDecorationsForVariable(id, &storage_type, &decorations,
sc != ast::StorageClass::kPrivate)) { address_space != ast::AddressSpace::kPrivate)) {
return nullptr; return nullptr;
} }
auto sym = builder_.Symbols().Register(namer_.Name(id)); auto sym = builder_.Symbols().Register(namer_.Name(id));
return create<ast::Var>(Source{}, sym, storage_type->Build(builder_), sc, access, constructor, return create<ast::Var>(Source{}, sym, storage_type->Build(builder_), address_space, access,
decorations); constructor, decorations);
} }
ast::Let* ParserImpl::MakeLet(uint32_t id, const Type* type, const ast::Expression* constructor) { ast::Let* ParserImpl::MakeLet(uint32_t id, const Type* type, const ast::Expression* constructor) {
@ -2486,7 +2486,7 @@ const Pointer* ParserImpl::GetTypeForHandleVar(const spvtools::opt::Instruction&
} }
// Form the pointer type. // Form the pointer type.
auto* result = ty_.Pointer(ast_store_type, ast::StorageClass::kHandle); auto* result = ty_.Pointer(ast_store_type, ast::AddressSpace::kHandle);
// Remember it for later. // Remember it for later.
handle_type_[&var] = result; handle_type_[&var] = result;
return result; return result;

View File

@ -50,7 +50,7 @@ TINT_END_DISABLE_WARNING(NEWLINE_EOF);
/// ///
/// A WGSL "handle" is an opaque object used for accessing a resource via /// A WGSL "handle" is an opaque object used for accessing a resource via
/// special builtins. In SPIR-V, a handle is stored a variable in the /// special builtins. In SPIR-V, a handle is stored a variable in the
/// UniformConstant storage class. The handles supported by SPIR-V are: /// UniformConstant address space. The handles supported by SPIR-V are:
/// - images, both sampled texture and storage image /// - images, both sampled texture and storage image
/// - samplers /// - samplers
/// - combined image+sampler /// - combined image+sampler
@ -424,14 +424,14 @@ class ParserImpl : Reader {
/// Creates an AST 'var' node for a SPIR-V ID, including any attached decorations, unless it's /// Creates an AST 'var' node for a SPIR-V ID, including any attached decorations, unless it's
/// an ignorable builtin variable. /// an ignorable builtin variable.
/// @param id the SPIR-V result ID /// @param id the SPIR-V result ID
/// @param sc the storage class, which cannot be ast::StorageClass::kNone /// @param address_space the address space, which cannot be ast::AddressSpace::kNone
/// @param storage_type the storage type of the variable /// @param storage_type the storage type of the variable
/// @param constructor the variable constructor /// @param constructor the variable constructor
/// @param decorations the variable decorations /// @param decorations the variable decorations
/// @returns a new Variable node, or null in the ignorable variable case and /// @returns a new Variable node, or null in the ignorable variable case and
/// in the error case /// in the error case
ast::Var* MakeVar(uint32_t id, ast::Var* MakeVar(uint32_t id,
ast::StorageClass sc, ast::AddressSpace address_space,
const Type* storage_type, const Type* storage_type,
const ast::Expression* constructor, const ast::Expression* constructor,
AttributeList decorations); AttributeList decorations);
@ -583,7 +583,7 @@ class ParserImpl : Reader {
/// The ID of the type of a pointer to the struct in the Output storage /// The ID of the type of a pointer to the struct in the Output storage
/// class class. /// class class.
uint32_t pointer_type_id = 0; uint32_t pointer_type_id = 0;
/// The SPIR-V storage class. /// The SPIR-V address space.
SpvStorageClass storage_class = SpvStorageClassOutput; SpvStorageClass storage_class = SpvStorageClassOutput;
/// The ID of the type of a pointer to the Position member. /// The ID of the type of a pointer to the Position member.
uint32_t position_member_pointer_type_id = 0; uint32_t position_member_pointer_type_id = 0;
@ -640,8 +640,8 @@ class ParserImpl : Reader {
Usage GetHandleUsage(uint32_t id) const; Usage GetHandleUsage(uint32_t id) const;
/// Returns the SPIR-V type for the sampler or image type for the given /// Returns the SPIR-V type for the sampler or image type for the given
/// variable in UniformConstant storage class, or function parameter pointing /// variable in UniformConstant address space, or function parameter pointing
/// into the UniformConstant storage class . Returns null and emits an /// into the UniformConstant address space . Returns null and emits an
/// error on failure. /// error on failure.
/// @param var the OpVariable instruction or OpFunctionParameter /// @param var the OpVariable instruction or OpFunctionParameter
/// @returns the Tint AST type for the sampler or texture, or null on error /// @returns the Tint AST type for the sampler or texture, or null on error
@ -649,7 +649,7 @@ class ParserImpl : Reader {
const spvtools::opt::Instruction& var); const spvtools::opt::Instruction& var);
/// Returns the AST type for the pointer-to-sampler or pointer-to-texture type /// Returns the AST type for the pointer-to-sampler or pointer-to-texture type
/// for the given variable in UniformConstant storage class. Returns null and /// for the given variable in UniformConstant address space. Returns null and
/// emits an error on failure. /// emits an error on failure.
/// @param var the OpVariable instruction /// @param var the OpVariable instruction
/// @returns the Tint AST type for the poiner-to-{sampler|texture} or null on /// @returns the Tint AST type for the poiner-to-{sampler|texture} or null on
@ -841,8 +841,8 @@ class ParserImpl : Reader {
// - an array, runtime array containing one of these // - an array, runtime array containing one of these
// - a pointer type to one of these // - a pointer type to one of these
// These are the types "enclosing" a buffer block with the old style // These are the types "enclosing" a buffer block with the old style
// representation: using Uniform storage class and BufferBlock decoration // representation: using Uniform address space and BufferBlock decoration
// on the struct. The new style is to use the StorageBuffer storage class // on the struct. The new style is to use the StorageBuffer address space
// and Block decoration. // and Block decoration.
std::unordered_set<uint32_t> remap_buffer_block_type_; std::unordered_set<uint32_t> remap_buffer_block_type_;

View File

@ -709,11 +709,11 @@ OpFunctionEnd
EXPECT_THAT(p->error(), Eq("SPIR-V pointer type with ID 3 has invalid pointee type 42")); EXPECT_THAT(p->error(), Eq("SPIR-V pointer type with ID 3 has invalid pointee type 42"));
} }
TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidStorageClass) { TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidAddressSpace) {
// Disallow invalid storage class // Disallow invalid address space
auto p = parser(test::Assemble(Preamble() + R"( auto p = parser(test::Assemble(Preamble() + R"(
%1 = OpTypeFloat 32 %1 = OpTypeFloat 32
%3 = OpTypePointer !999 %1 ; Special syntax to inject 999 as the storage class %3 = OpTypePointer !999 %1 ; Special syntax to inject 999 as the address space
)" + MainBody())); )" + MainBody()));
// TODO(dneto): I can't get it past module building. // TODO(dneto): I can't get it past module building.
EXPECT_FALSE(p->BuildInternalModule()) << p->error(); EXPECT_FALSE(p->BuildInternalModule()) << p->error();
@ -731,7 +731,7 @@ TEST_F(SpvParserTest, ConvertType_PointerInput) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kPrivate);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -747,7 +747,7 @@ TEST_F(SpvParserTest, ConvertType_PointerOutput) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kPrivate);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -763,7 +763,7 @@ TEST_F(SpvParserTest, ConvertType_PointerUniform) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kUniform); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kUniform);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -779,7 +779,7 @@ TEST_F(SpvParserTest, ConvertType_PointerWorkgroup) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kWorkgroup); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -795,7 +795,7 @@ TEST_F(SpvParserTest, ConvertType_PointerUniformConstant) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kNone); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kNone);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -811,7 +811,7 @@ TEST_F(SpvParserTest, ConvertType_PointerStorageBuffer) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kStorage); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kStorage);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -827,7 +827,7 @@ TEST_F(SpvParserTest, ConvertType_PointerPrivate) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kPrivate);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -843,7 +843,7 @@ TEST_F(SpvParserTest, ConvertType_PointerFunction) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_TRUE(ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ty->type->Is<F32>());
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kFunction); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kFunction);
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
} }
@ -862,12 +862,12 @@ TEST_F(SpvParserTest, ConvertType_PointerToPointer) {
auto* ptr_ty = type->As<Pointer>(); auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr); EXPECT_NE(ptr_ty, nullptr);
EXPECT_EQ(ptr_ty->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(ptr_ty->address_space, ast::AddressSpace::kPrivate);
EXPECT_TRUE(ptr_ty->type->Is<Pointer>()); EXPECT_TRUE(ptr_ty->type->Is<Pointer>());
auto* ptr_ptr_ty = ptr_ty->type->As<Pointer>(); auto* ptr_ptr_ty = ptr_ty->type->As<Pointer>();
EXPECT_NE(ptr_ptr_ty, nullptr); EXPECT_NE(ptr_ptr_ty, nullptr);
EXPECT_EQ(ptr_ptr_ty->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(ptr_ptr_ty->address_space, ast::AddressSpace::kPrivate);
EXPECT_TRUE(ptr_ptr_ty->type->Is<F32>()); EXPECT_TRUE(ptr_ptr_ty->type->Is<F32>());
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());

View File

@ -119,7 +119,7 @@ TEST_F(SpvModuleScopeVarParserTest, NoVar) {
EXPECT_THAT(module_ast, Not(HasSubstr("Variable"))) << module_ast; EXPECT_THAT(module_ast, Not(HasSubstr("Variable"))) << module_ast;
} }
TEST_F(SpvModuleScopeVarParserTest, BadStorageClass_NotAWebGPUStorageClass) { TEST_F(SpvModuleScopeVarParserTest, BadAddressSpace_NotAWebGPUAddressSpace) {
auto p = parser(test::Assemble(Preamble() + FragMain() + R"( auto p = parser(test::Assemble(Preamble() + FragMain() + R"(
%float = OpTypeFloat 32 %float = OpTypeFloat 32
%ptr = OpTypePointer CrossWorkgroup %float %ptr = OpTypePointer CrossWorkgroup %float
@ -135,7 +135,7 @@ TEST_F(SpvModuleScopeVarParserTest, BadStorageClass_NotAWebGPUStorageClass) {
EXPECT_THAT(p->error(), HasSubstr("unknown SPIR-V storage class: 5")); EXPECT_THAT(p->error(), HasSubstr("unknown SPIR-V storage class: 5"));
} }
TEST_F(SpvModuleScopeVarParserTest, BadStorageClass_Function) { TEST_F(SpvModuleScopeVarParserTest, BadAddressSpace_Function) {
auto p = parser(test::Assemble(Preamble() + FragMain() + R"( auto p = parser(test::Assemble(Preamble() + FragMain() + R"(
%float = OpTypeFloat 32 %float = OpTypeFloat 32
%ptr = OpTypePointer Function %float %ptr = OpTypePointer Function %float

View File

@ -50,11 +50,11 @@ namespace tint::reader::spirv {
namespace { namespace {
struct PointerHasher { struct PointerHasher {
size_t operator()(const Pointer& t) const { return utils::Hash(t.type, t.storage_class); } size_t operator()(const Pointer& t) const { return utils::Hash(t.type, t.address_space); }
}; };
struct ReferenceHasher { struct ReferenceHasher {
size_t operator()(const Reference& t) const { return utils::Hash(t.type, t.storage_class); } size_t operator()(const Reference& t) const { return utils::Hash(t.type, t.address_space); }
}; };
struct VectorHasher { struct VectorHasher {
@ -107,10 +107,10 @@ struct StorageTextureHasher {
// Equality operators // Equality operators
//! @cond Doxygen_Suppress //! @cond Doxygen_Suppress
static bool operator==(const Pointer& a, const Pointer& b) { static bool operator==(const Pointer& a, const Pointer& b) {
return a.type == b.type && a.storage_class == b.storage_class; return a.type == b.type && a.address_space == b.address_space;
} }
static bool operator==(const Reference& a, const Reference& b) { static bool operator==(const Reference& a, const Reference& b) {
return a.type == b.type && a.storage_class == b.storage_class; return a.type == b.type && a.address_space == b.address_space;
} }
static bool operator==(const Vector& a, const Vector& b) { static bool operator==(const Vector& a, const Vector& b) {
return a.type == b.type && a.size == b.size; return a.type == b.type && a.size == b.size;
@ -170,14 +170,14 @@ Type::~Type() = default;
Texture::~Texture() = default; Texture::~Texture() = default;
Pointer::Pointer(const Type* t, ast::StorageClass s) : type(t), storage_class(s) {} Pointer::Pointer(const Type* t, ast::AddressSpace s) : type(t), address_space(s) {}
Pointer::Pointer(const Pointer&) = default; Pointer::Pointer(const Pointer&) = default;
const ast::Type* Pointer::Build(ProgramBuilder& b) const { const ast::Type* Pointer::Build(ProgramBuilder& b) const {
return b.ty.pointer(type->Build(b), storage_class); return b.ty.pointer(type->Build(b), address_space);
} }
Reference::Reference(const Type* t, ast::StorageClass s) : type(t), storage_class(s) {} Reference::Reference(const Type* t, ast::AddressSpace s) : type(t), address_space(s) {}
Reference::Reference(const Reference&) = default; Reference::Reference(const Reference&) = default;
const ast::Type* Reference::Build(ProgramBuilder& b) const { const ast::Type* Reference::Build(ProgramBuilder& b) const {
@ -438,12 +438,12 @@ const spirv::I32* TypeManager::I32() {
return state->i32_; return state->i32_;
} }
const spirv::Pointer* TypeManager::Pointer(const Type* el, ast::StorageClass sc) { const spirv::Pointer* TypeManager::Pointer(const Type* el, ast::AddressSpace address_space) {
return state->pointers_.Get(el, sc); return state->pointers_.Get(el, address_space);
} }
const spirv::Reference* TypeManager::Reference(const Type* el, ast::StorageClass sc) { const spirv::Reference* TypeManager::Reference(const Type* el, ast::AddressSpace address_space) {
return state->references_.Get(el, sc); return state->references_.Get(el, address_space);
} }
const spirv::Vector* TypeManager::Vector(const Type* el, uint32_t size) { const spirv::Vector* TypeManager::Vector(const Type* el, uint32_t size) {
@ -519,13 +519,13 @@ std::string I32::String() const {
std::string Pointer::String() const { std::string Pointer::String() const {
std::stringstream ss; std::stringstream ss;
ss << "ptr<" << utils::ToString(storage_class) << ", " << type->String() + ">"; ss << "ptr<" << utils::ToString(address_space) << ", " << type->String() + ">";
return ss.str(); return ss.str();
} }
std::string Reference::String() const { std::string Reference::String() const {
std::stringstream ss; std::stringstream ss;
ss << "ref<" + utils::ToString(storage_class) << ", " << type->String() << ">"; ss << "ref<" + utils::ToString(address_space) << ", " << type->String() << ">";
return ss.str(); return ss.str();
} }

View File

@ -20,8 +20,8 @@
#include <vector> #include <vector>
#include "src/tint/ast/access.h" #include "src/tint/ast/access.h"
#include "src/tint/ast/address_space.h"
#include "src/tint/ast/sampler.h" #include "src/tint/ast/sampler.h"
#include "src/tint/ast/storage_class.h"
#include "src/tint/ast/storage_texture.h" #include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/texture.h" #include "src/tint/ast/texture.h"
#include "src/tint/castable.h" #include "src/tint/castable.h"
@ -161,8 +161,8 @@ struct I32 final : public Castable<I32, Type> {
struct Pointer final : public Castable<Pointer, Type> { struct Pointer final : public Castable<Pointer, Type> {
/// Constructor /// Constructor
/// @param ty the store type /// @param ty the store type
/// @param sc the pointer storage class /// @param sc the pointer address space
Pointer(const Type* ty, ast::StorageClass sc); Pointer(const Type* ty, ast::AddressSpace sc);
/// Copy constructor /// Copy constructor
/// @param other the other type to copy /// @param other the other type to copy
@ -179,8 +179,8 @@ struct Pointer final : public Castable<Pointer, Type> {
/// the store type /// the store type
Type const* const type; Type const* const type;
/// the pointer storage class /// the pointer address space
ast::StorageClass const storage_class; ast::AddressSpace const address_space;
}; };
/// `ref<SC, T>` type /// `ref<SC, T>` type
@ -189,8 +189,8 @@ struct Pointer final : public Castable<Pointer, Type> {
struct Reference final : public Castable<Reference, Type> { struct Reference final : public Castable<Reference, Type> {
/// Constructor /// Constructor
/// @param ty the referenced type /// @param ty the referenced type
/// @param sc the reference storage class /// @param sc the reference address space
Reference(const Type* ty, ast::StorageClass sc); Reference(const Type* ty, ast::AddressSpace sc);
/// Copy constructor /// Copy constructor
/// @param other the other type to copy /// @param other the other type to copy
@ -207,8 +207,8 @@ struct Reference final : public Castable<Reference, Type> {
/// the store type /// the store type
Type const* const type; Type const* const type;
/// the pointer storage class /// the pointer address space
ast::StorageClass const storage_class; ast::AddressSpace const address_space;
}; };
/// `vecN<T>` type /// `vecN<T>` type
@ -534,15 +534,15 @@ class TypeManager {
/// @return a I32 type. Repeated calls will return the same pointer. /// @return a I32 type. Repeated calls will return the same pointer.
const spirv::I32* I32(); const spirv::I32* I32();
/// @param ty the store type /// @param ty the store type
/// @param sc the pointer storage class /// @param address_space the pointer address space
/// @return a Pointer type. Repeated calls with the same arguments will return /// @return a Pointer type. Repeated calls with the same arguments will return
/// the same pointer. /// the same pointer.
const spirv::Pointer* Pointer(const Type* ty, ast::StorageClass sc); const spirv::Pointer* Pointer(const Type* ty, ast::AddressSpace address_space);
/// @param ty the referenced type /// @param ty the referenced type
/// @param sc the reference storage class /// @param address_space the reference address space
/// @return a Reference type. Repeated calls with the same arguments will /// @return a Reference type. Repeated calls with the same arguments will
/// return the same pointer. /// return the same pointer.
const spirv::Reference* Reference(const Type* ty, ast::StorageClass sc); const spirv::Reference* Reference(const Type* ty, ast::AddressSpace address_space);
/// @param ty the element type /// @param ty the element type
/// @param sz the number of elements in the vector /// @param sz the number of elements in the vector
/// @return a Vector type. Repeated calls with the same arguments will return /// @return a Vector type. Repeated calls with the same arguments will return

View File

@ -28,8 +28,8 @@ TEST(SpvParserTypeTest, SameArgumentsGivesSamePointer) {
EXPECT_EQ(ty.U32(), ty.U32()); EXPECT_EQ(ty.U32(), ty.U32());
EXPECT_EQ(ty.F32(), ty.F32()); EXPECT_EQ(ty.F32(), ty.F32());
EXPECT_EQ(ty.I32(), ty.I32()); EXPECT_EQ(ty.I32(), ty.I32());
EXPECT_EQ(ty.Pointer(ty.I32(), ast::StorageClass::kNone), EXPECT_EQ(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
ty.Pointer(ty.I32(), ast::StorageClass::kNone)); ty.Pointer(ty.I32(), ast::AddressSpace::kNone));
EXPECT_EQ(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 3)); EXPECT_EQ(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 3));
EXPECT_EQ(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.I32(), 3, 2)); EXPECT_EQ(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.I32(), 3, 2));
EXPECT_EQ(ty.Array(ty.I32(), 3, 2), ty.Array(ty.I32(), 3, 2)); EXPECT_EQ(ty.Array(ty.I32(), 3, 2), ty.Array(ty.I32(), 3, 2));
@ -53,10 +53,10 @@ TEST(SpvParserTypeTest, DifferentArgumentsGivesDifferentPointer) {
Symbol sym_b(Symbol(2, {})); Symbol sym_b(Symbol(2, {}));
TypeManager ty; TypeManager ty;
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone), EXPECT_NE(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
ty.Pointer(ty.U32(), ast::StorageClass::kNone)); ty.Pointer(ty.U32(), ast::AddressSpace::kNone));
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone), EXPECT_NE(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
ty.Pointer(ty.I32(), ast::StorageClass::kIn)); ty.Pointer(ty.I32(), ast::AddressSpace::kIn));
EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.U32(), 3)); EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.U32(), 3));
EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 2)); EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 2));
EXPECT_NE(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.U32(), 3, 2)); EXPECT_NE(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.U32(), 3, 2));

View File

@ -206,12 +206,12 @@ ParserImpl::VarDeclInfo::VarDeclInfo(const VarDeclInfo&) = default;
ParserImpl::VarDeclInfo::VarDeclInfo(Source source_in, ParserImpl::VarDeclInfo::VarDeclInfo(Source source_in,
std::string name_in, std::string name_in,
ast::StorageClass storage_class_in, ast::AddressSpace address_space_in,
ast::Access access_in, ast::Access access_in,
const ast::Type* type_in) const ast::Type* type_in)
: source(std::move(source_in)), : source(std::move(source_in)),
name(std::move(name_in)), name(std::move(name_in)),
storage_class(storage_class_in), address_space(address_space_in),
access(access_in), access(access_in),
type(type_in) {} type(type_in) {}
@ -594,7 +594,7 @@ Maybe<const ast::Variable*> ParserImpl::global_variable_decl(AttributeList& attr
return create<ast::Var>(decl->source, // source return create<ast::Var>(decl->source, // source
builder_.Symbols().Register(decl->name), // symbol builder_.Symbols().Register(decl->name), // symbol
decl->type, // type decl->type, // type
decl->storage_class, // storage class decl->address_space, // address space
decl->access, // access control decl->access, // access control
initializer, // initializer initializer, // initializer
std::move(attrs)); // attributes std::move(attrs)); // attributes
@ -697,7 +697,7 @@ Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
return Failure::kErrored; return Failure::kErrored;
} }
return VarDeclInfo{decl->source, decl->name, vq.storage_class, vq.access, decl->type}; return VarDeclInfo{decl->source, decl->name, vq.address_space, vq.access, decl->type};
} }
// texture_and_sampler_types // texture_and_sampler_types
@ -1208,7 +1208,7 @@ Expect<const ast::Type*> ParserImpl::expect_type(std::string_view use) {
Expect<const ast::Type*> ParserImpl::expect_type_decl_pointer(const Source& s) { Expect<const ast::Type*> ParserImpl::expect_type_decl_pointer(const Source& s) {
const char* use = "ptr declaration"; const char* use = "ptr declaration";
auto storage_class = ast::StorageClass::kNone; auto address_space = ast::AddressSpace::kNone;
auto access = ast::Access::kUndefined; auto access = ast::Access::kUndefined;
auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> { auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> {
@ -1216,7 +1216,7 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_pointer(const Source& s) {
if (sc.errored) { if (sc.errored) {
return Failure::kErrored; return Failure::kErrored;
} }
storage_class = sc.value; address_space = sc.value;
if (!expect(use, Token::Type::kComma)) { if (!expect(use, Token::Type::kComma)) {
return Failure::kErrored; return Failure::kErrored;
@ -1242,7 +1242,7 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_pointer(const Source& s) {
return Failure::kErrored; return Failure::kErrored;
} }
return builder_.ty.pointer(make_source_range_from(s), subtype.value, storage_class, access); return builder_.ty.pointer(make_source_range_from(s), subtype.value, address_space, access);
} }
// LESS_THAN type_decl GREATER_THAN // LESS_THAN type_decl GREATER_THAN
@ -1329,19 +1329,19 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(const Source& s,
// | 'storage' // | 'storage'
// //
// Note, we also parse `push_constant` from the experimental extension // Note, we also parse `push_constant` from the experimental extension
Expect<ast::StorageClass> ParserImpl::expect_address_space(std::string_view use) { Expect<ast::AddressSpace> ParserImpl::expect_address_space(std::string_view use) {
auto& t = peek(); auto& t = peek();
auto ident = expect_ident("storage class"); auto ident = expect_ident("address space");
if (ident.errored) { if (ident.errored) {
return Failure::kErrored; return Failure::kErrored;
} }
auto storage_class = ast::ParseStorageClass(ident.value); auto address_space = ast::ParseAddressSpace(ident.value);
if (storage_class == ast::StorageClass::kInvalid) { if (address_space == ast::AddressSpace::kInvalid) {
return add_error(t.source(), "invalid storage class", use); return add_error(t.source(), "invalid address space", use);
} }
return {storage_class, t.source()}; return {address_space, t.source()};
} }
// struct_decl // struct_decl
@ -1988,7 +1988,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_statement() {
auto* var = create<ast::Var>(decl->source, // source auto* var = create<ast::Var>(decl->source, // source
builder_.Symbols().Register(decl->name), // symbol builder_.Symbols().Register(decl->name), // symbol
decl->type, // type decl->type, // type
decl->storage_class, // storage class decl->address_space, // address space
decl->access, // access control decl->access, // access control
initializer, // initializer initializer, // initializer
utils::Empty); // attributes utils::Empty); // attributes

View File

@ -278,12 +278,12 @@ class ParserImpl {
/// Constructor /// Constructor
/// @param source_in variable declaration source /// @param source_in variable declaration source
/// @param name_in variable name /// @param name_in variable name
/// @param storage_class_in variable storage class /// @param address_space_in variable address space
/// @param access_in variable access control /// @param access_in variable access control
/// @param type_in variable type /// @param type_in variable type
VarDeclInfo(Source source_in, VarDeclInfo(Source source_in,
std::string name_in, std::string name_in,
ast::StorageClass storage_class_in, ast::AddressSpace address_space_in,
ast::Access access_in, ast::Access access_in,
const ast::Type* type_in); const ast::Type* type_in);
/// Destructor /// Destructor
@ -293,8 +293,8 @@ class ParserImpl {
Source source; Source source;
/// Variable name /// Variable name
std::string name; std::string name;
/// Variable storage class /// Variable address space
ast::StorageClass storage_class = ast::StorageClass::kNone; ast::AddressSpace address_space = ast::AddressSpace::kNone;
/// Variable access control /// Variable access control
ast::Access access = ast::Access::kUndefined; ast::Access access = ast::Access::kUndefined;
/// Variable type /// Variable type
@ -303,8 +303,8 @@ class ParserImpl {
/// VariableQualifier contains the parsed information for a variable qualifier /// VariableQualifier contains the parsed information for a variable qualifier
struct VariableQualifier { struct VariableQualifier {
/// The variable's storage class /// The variable's address space
ast::StorageClass storage_class = ast::StorageClass::kNone; ast::AddressSpace address_space = ast::AddressSpace::kNone;
/// The variable's access control /// The variable's access control
ast::Access access = ast::Access::kUndefined; ast::Access access = ast::Access::kUndefined;
}; };
@ -460,8 +460,8 @@ class ParserImpl {
Maybe<const ast::Type*> type_decl(); Maybe<const ast::Type*> type_decl();
/// Parses an `address_space` grammar element, erroring on parse failure. /// Parses an `address_space` grammar element, erroring on parse failure.
/// @param use a description of what was being parsed if an error was raised. /// @param use a description of what was being parsed if an error was raised.
/// @returns the address space or StorageClass::kNone if none matched /// @returns the address space or ast::AddressSpace::kNone if none matched
Expect<ast::StorageClass> expect_address_space(std::string_view use); Expect<ast::AddressSpace> expect_address_space(std::string_view use);
/// Parses a `struct_decl` grammar element. /// Parses a `struct_decl` grammar element.
/// @returns the struct type or nullptr on error /// @returns the struct type or nullptr on error
Maybe<const ast::Struct*> struct_decl(); Maybe<const ast::Struct*> struct_decl();

View File

@ -17,18 +17,18 @@
namespace tint::reader::wgsl { namespace tint::reader::wgsl {
namespace { namespace {
struct StorageClassData { struct AddressSpaceData {
const char* input; const char* input;
ast::StorageClass result; ast::AddressSpace result;
}; };
inline std::ostream& operator<<(std::ostream& out, StorageClassData data) { inline std::ostream& operator<<(std::ostream& out, AddressSpaceData data) {
out << std::string(data.input); out << std::string(data.input);
return out; return out;
} }
class ParserStorageClassTest : public ParserImplTestWithParam<StorageClassData> {}; class ParserAddressSpaceTest : public ParserImplTestWithParam<AddressSpaceData> {};
TEST_P(ParserStorageClassTest, Parses) { TEST_P(ParserAddressSpaceTest, Parses) {
auto params = GetParam(); auto params = GetParam();
auto p = parser(params.input); auto p = parser(params.input);
@ -42,19 +42,19 @@ TEST_P(ParserStorageClassTest, Parses) {
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
ParserStorageClassTest, ParserAddressSpaceTest,
testing::Values(StorageClassData{"uniform", ast::StorageClass::kUniform}, testing::Values(AddressSpaceData{"uniform", ast::AddressSpace::kUniform},
StorageClassData{"workgroup", ast::StorageClass::kWorkgroup}, AddressSpaceData{"workgroup", ast::AddressSpace::kWorkgroup},
StorageClassData{"storage", ast::StorageClass::kStorage}, AddressSpaceData{"storage", ast::AddressSpace::kStorage},
StorageClassData{"private", ast::StorageClass::kPrivate}, AddressSpaceData{"private", ast::AddressSpace::kPrivate},
StorageClassData{"function", ast::StorageClass::kFunction})); AddressSpaceData{"function", ast::AddressSpace::kFunction}));
TEST_F(ParserImplTest, StorageClass_NoMatch) { TEST_F(ParserImplTest, AddressSpace_NoMatch) {
auto p = parser("not-a-storage-class"); auto p = parser("not-a-address-space");
auto sc = p->expect_address_space("test"); auto sc = p->expect_address_space("test");
EXPECT_EQ(sc.errored, true); EXPECT_EQ(sc.errored, true);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:1: invalid storage class for test"); EXPECT_EQ(p->error(), "1:1: invalid address space for test");
} }
} // namespace } // namespace

View File

@ -1105,9 +1105,9 @@ var i : ptr<private u32>;
)"); )");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingStorageClass) { TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingAddressSpace) {
EXPECT("var i : ptr<meow, u32>;", EXPECT("var i : ptr<meow, u32>;",
R"(test.wgsl:1:13 error: invalid storage class for ptr declaration R"(test.wgsl:1:13 error: invalid address space for ptr declaration
var i : ptr<meow, u32>; var i : ptr<meow, u32>;
^^^^ ^^^^
)"); )");
@ -1139,7 +1139,7 @@ var i : atomic<u32 x;
TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) { TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) {
EXPECT("var<fish> i : i32", EXPECT("var<fish> i : i32",
R"(test.wgsl:1:5 error: invalid storage class for variable declaration R"(test.wgsl:1:5 error: invalid address space for variable declaration
var<fish> i : i32 var<fish> i : i32
^^^^ ^^^^
)"); )");

View File

@ -31,7 +31,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
EXPECT_TRUE(var->type->Is<ast::F32>()); EXPECT_TRUE(var->type->Is<ast::F32>());
EXPECT_EQ(var->declared_storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(var->declared_address_space, ast::AddressSpace::kPrivate);
EXPECT_EQ(var->source.range.begin.line, 1u); EXPECT_EQ(var->source.range.begin.line, 1u);
EXPECT_EQ(var->source.range.begin.column, 14u); EXPECT_EQ(var->source.range.begin.column, 14u);
@ -55,7 +55,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
EXPECT_TRUE(var->type->Is<ast::F32>()); EXPECT_TRUE(var->type->Is<ast::F32>());
EXPECT_EQ(var->declared_storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(var->declared_address_space, ast::AddressSpace::kPrivate);
EXPECT_EQ(var->source.range.begin.line, 1u); EXPECT_EQ(var->source.range.begin.line, 1u);
EXPECT_EQ(var->source.range.begin.column, 14u); EXPECT_EQ(var->source.range.begin.column, 14u);
@ -81,7 +81,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(var->type, nullptr); ASSERT_NE(var->type, nullptr);
EXPECT_TRUE(var->type->Is<ast::F32>()); EXPECT_TRUE(var->type->Is<ast::F32>());
EXPECT_EQ(var->declared_storage_class, ast::StorageClass::kUniform); EXPECT_EQ(var->declared_address_space, ast::AddressSpace::kUniform);
EXPECT_EQ(var->source.range.begin.line, 1u); EXPECT_EQ(var->source.range.begin.line, 1u);
EXPECT_EQ(var->source.range.begin.column, 36u); EXPECT_EQ(var->source.range.begin.column, 36u);
@ -112,7 +112,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute_MulitpleGroups) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(var->type, nullptr); ASSERT_NE(var->type, nullptr);
EXPECT_TRUE(var->type->Is<ast::F32>()); EXPECT_TRUE(var->type->Is<ast::F32>());
EXPECT_EQ(var->declared_storage_class, ast::StorageClass::kUniform); EXPECT_EQ(var->declared_address_space, ast::AddressSpace::kUniform);
EXPECT_EQ(var->source.range.begin.line, 1u); EXPECT_EQ(var->source.range.begin.line, 1u);
EXPECT_EQ(var->source.range.begin.column, 36u); EXPECT_EQ(var->source.range.begin.column, 36u);
@ -165,7 +165,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
EXPECT_TRUE(e.errored); EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched); EXPECT_FALSE(e.matched);
EXPECT_EQ(e.value, nullptr); EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable declaration"); EXPECT_EQ(p->error(), "1:5: invalid address space for variable declaration");
} }
} // namespace } // namespace

View File

@ -176,7 +176,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::F32>()); ASSERT_TRUE(ptr->type->Is<ast::F32>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
} }
@ -191,7 +191,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_WithAccess) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::F32>()); ASSERT_TRUE(ptr->type->Is<ast::F32>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
ASSERT_EQ(ptr->access, ast::Access::kRead); ASSERT_EQ(ptr->access, ast::Access::kRead);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}}));
} }
@ -207,7 +207,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::Vector>()); ASSERT_TRUE(ptr->type->Is<ast::Vector>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
auto* vec = ptr->type->As<ast::Vector>(); auto* vec = ptr->type->As<ast::Vector>();
ASSERT_EQ(vec->width, 2u); ASSERT_EQ(vec->width, 2u);
@ -245,7 +245,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThanAfterAccess) {
ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration"); ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterStorageClass) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAddressSpace) {
auto p = parser("ptr<function f32>"); auto p = parser("ptr<function f32>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
@ -265,14 +265,14 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAccess) {
ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration"); ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingAddressSpace) {
auto p = parser("ptr<, f32>"); auto p = parser("ptr<, f32>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected identifier for storage class"); ASSERT_EQ(p->error(), "1:5: expected identifier for address space");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) { TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
@ -302,17 +302,17 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected identifier for storage class"); ASSERT_EQ(p->error(), "1:5: expected identifier for address space");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) { TEST_F(ParserImplTest, TypeDecl_Ptr_BadAddressSpace) {
auto p = parser("ptr<unknown, f32>"); auto p = parser("ptr<unknown, f32>");
auto t = p->type_decl(); auto t = p->type_decl();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration"); ASSERT_EQ(p->error(), "1:5: invalid address space for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDecl_Ptr_BadAccess) { TEST_F(ParserImplTest, TypeDecl_Ptr_BadAccess) {

View File

@ -167,7 +167,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::F32>()); ASSERT_TRUE(ptr->type->Is<ast::F32>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
} }
@ -182,7 +182,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_WithAccess) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::F32>()); ASSERT_TRUE(ptr->type->Is<ast::F32>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
ASSERT_EQ(ptr->access, ast::Access::kRead); ASSERT_EQ(ptr->access, ast::Access::kRead);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}}));
} }
@ -198,7 +198,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_ToVec) {
auto* ptr = t.value->As<ast::Pointer>(); auto* ptr = t.value->As<ast::Pointer>();
ASSERT_TRUE(ptr->type->Is<ast::Vector>()); ASSERT_TRUE(ptr->type->Is<ast::Vector>());
ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction); ASSERT_EQ(ptr->address_space, ast::AddressSpace::kFunction);
auto* vec = ptr->type->As<ast::Vector>(); auto* vec = ptr->type->As<ast::Vector>();
ASSERT_EQ(vec->width, 2u); ASSERT_EQ(vec->width, 2u);
@ -236,7 +236,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingGreaterThanAfterAccess) {
ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration"); ASSERT_EQ(p->error(), "1:24: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterStorageClass) { TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAddressSpace) {
auto p = parser("ptr<function f32>"); auto p = parser("ptr<function f32>");
auto t = p->type_decl_without_ident(); auto t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
@ -256,14 +256,14 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAccess) {
ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration"); ASSERT_EQ(p->error(), "1:19: expected '>' for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingStorageClass) { TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingAddressSpace) {
auto p = parser("ptr<, f32>"); auto p = parser("ptr<, f32>");
auto t = p->type_decl_without_ident(); auto t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected identifier for storage class"); ASSERT_EQ(p->error(), "1:5: expected identifier for address space");
} }
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingType) { TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingType) {
@ -293,17 +293,17 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingParams) {
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected identifier for storage class"); ASSERT_EQ(p->error(), "1:5: expected identifier for address space");
} }
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_BadStorageClass) { TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_BadAddressSpace) {
auto p = parser("ptr<unknown, f32>"); auto p = parser("ptr<unknown, f32>");
auto t = p->type_decl_without_ident(); auto t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored); EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched); EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr); ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error()); ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration"); ASSERT_EQ(p->error(), "1:5: invalid address space for ptr declaration");
} }
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_BadAccess) { TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_BadAccess) {

View File

@ -72,7 +72,7 @@ TEST_F(ParserImplTest, VariableDecl_MissingVar) {
ASSERT_TRUE(t.IsIdentifier()); ASSERT_TRUE(t.IsIdentifier());
} }
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) { TEST_F(ParserImplTest, VariableDecl_WithAddressSpace) {
auto p = parser("var<private> my_var : f32"); auto p = parser("var<private> my_var : f32");
auto v = p->variable_decl(); auto v = p->variable_decl();
EXPECT_TRUE(v.matched); EXPECT_TRUE(v.matched);
@ -80,7 +80,7 @@ TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_EQ(v->name, "my_var"); EXPECT_EQ(v->name, "my_var");
EXPECT_TRUE(v->type->Is<ast::F32>()); EXPECT_TRUE(v->type->Is<ast::F32>());
EXPECT_EQ(v->storage_class, ast::StorageClass::kPrivate); EXPECT_EQ(v->address_space, ast::AddressSpace::kPrivate);
EXPECT_EQ(v->source.range.begin.line, 1u); EXPECT_EQ(v->source.range.begin.line, 1u);
EXPECT_EQ(v->source.range.begin.column, 14u); EXPECT_EQ(v->source.range.begin.column, 14u);
@ -96,16 +96,16 @@ TEST_F(ParserImplTest, VariableDecl_WithPushConstant) {
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_EQ(v->name, "my_var"); EXPECT_EQ(v->name, "my_var");
EXPECT_TRUE(v->type->Is<ast::F32>()); EXPECT_TRUE(v->type->Is<ast::F32>());
EXPECT_EQ(v->storage_class, ast::StorageClass::kPushConstant); EXPECT_EQ(v->address_space, ast::AddressSpace::kPushConstant);
} }
TEST_F(ParserImplTest, VariableDecl_InvalidStorageClass) { TEST_F(ParserImplTest, VariableDecl_InvalidAddressSpace) {
auto p = parser("var<unknown> my_var : f32"); auto p = parser("var<unknown> my_var : f32");
auto v = p->variable_decl(); auto v = p->variable_decl();
EXPECT_FALSE(v.matched); EXPECT_FALSE(v.matched);
EXPECT_TRUE(v.errored); EXPECT_TRUE(v.errored);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable declaration"); EXPECT_EQ(p->error(), "1:5: invalid address space for variable declaration");
} }
} // namespace } // namespace

View File

@ -19,7 +19,7 @@ namespace {
struct VariableStorageData { struct VariableStorageData {
const char* input; const char* input;
ast::StorageClass storage_class; ast::AddressSpace address_space;
ast::Access access; ast::Access access;
}; };
inline std::ostream& operator<<(std::ostream& out, VariableStorageData data) { inline std::ostream& operator<<(std::ostream& out, VariableStorageData data) {
@ -29,7 +29,7 @@ inline std::ostream& operator<<(std::ostream& out, VariableStorageData data) {
class VariableQualifierTest : public ParserImplTestWithParam<VariableStorageData> {}; class VariableQualifierTest : public ParserImplTestWithParam<VariableStorageData> {};
TEST_P(VariableQualifierTest, ParsesStorageClass) { TEST_P(VariableQualifierTest, ParsesAddressSpace) {
auto params = GetParam(); auto params = GetParam();
auto p = parser(std::string("<") + params.input + ">"); auto p = parser(std::string("<") + params.input + ">");
@ -37,7 +37,7 @@ TEST_P(VariableQualifierTest, ParsesStorageClass) {
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_FALSE(sc.errored); EXPECT_FALSE(sc.errored);
EXPECT_TRUE(sc.matched); EXPECT_TRUE(sc.matched);
EXPECT_EQ(sc->storage_class, params.storage_class); EXPECT_EQ(sc->address_space, params.address_space);
EXPECT_EQ(sc->access, params.access); EXPECT_EQ(sc->access, params.access);
auto& t = p->next(); auto& t = p->next();
@ -47,14 +47,14 @@ INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
VariableQualifierTest, VariableQualifierTest,
testing::Values( testing::Values(
VariableStorageData{"uniform", ast::StorageClass::kUniform, ast::Access::kUndefined}, VariableStorageData{"uniform", ast::AddressSpace::kUniform, ast::Access::kUndefined},
VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup, ast::Access::kUndefined}, VariableStorageData{"workgroup", ast::AddressSpace::kWorkgroup, ast::Access::kUndefined},
VariableStorageData{"storage", ast::StorageClass::kStorage, ast::Access::kUndefined}, VariableStorageData{"storage", ast::AddressSpace::kStorage, ast::Access::kUndefined},
VariableStorageData{"private", ast::StorageClass::kPrivate, ast::Access::kUndefined}, VariableStorageData{"private", ast::AddressSpace::kPrivate, ast::Access::kUndefined},
VariableStorageData{"function", ast::StorageClass::kFunction, ast::Access::kUndefined}, VariableStorageData{"function", ast::AddressSpace::kFunction, ast::Access::kUndefined},
VariableStorageData{"storage, read", ast::StorageClass::kStorage, ast::Access::kRead}, VariableStorageData{"storage, read", ast::AddressSpace::kStorage, ast::Access::kRead},
VariableStorageData{"storage, write", ast::StorageClass::kStorage, ast::Access::kWrite}, VariableStorageData{"storage, write", ast::AddressSpace::kStorage, ast::Access::kWrite},
VariableStorageData{"storage, read_write", ast::StorageClass::kStorage, VariableStorageData{"storage, read_write", ast::AddressSpace::kStorage,
ast::Access::kReadWrite})); ast::Access::kReadWrite}));
TEST_F(ParserImplTest, VariableQualifier_NoMatch) { TEST_F(ParserImplTest, VariableQualifier_NoMatch) {
@ -63,7 +63,7 @@ TEST_F(ParserImplTest, VariableQualifier_NoMatch) {
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(sc.errored); EXPECT_TRUE(sc.errored);
EXPECT_FALSE(sc.matched); EXPECT_FALSE(sc.matched);
EXPECT_EQ(p->error(), "1:2: invalid storage class for variable declaration"); EXPECT_EQ(p->error(), "1:2: invalid address space for variable declaration");
} }
TEST_F(ParserImplTest, VariableQualifier_Empty) { TEST_F(ParserImplTest, VariableQualifier_Empty) {
@ -72,7 +72,7 @@ TEST_F(ParserImplTest, VariableQualifier_Empty) {
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(sc.errored); EXPECT_TRUE(sc.errored);
EXPECT_FALSE(sc.matched); EXPECT_FALSE(sc.matched);
EXPECT_EQ(p->error(), "1:2: expected identifier for storage class"); EXPECT_EQ(p->error(), "1:2: expected identifier for address space");
} }
TEST_F(ParserImplTest, VariableQualifier_MissingLessThan) { TEST_F(ParserImplTest, VariableQualifier_MissingLessThan) {

View File

@ -22,10 +22,10 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::resolver { namespace tint::resolver {
namespace { namespace {
using ResolverStorageClassLayoutValidationTest = ResolverTest; using ResolverAddressSpaceLayoutValidationTest = ResolverTest;
// Detect unaligned member for storage buffers // Detect unaligned member for storage buffers
TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember) { TEST_F(ResolverAddressSpaceLayoutValidationTest, StorageBuffer_UnalignedMember) {
// struct S { // struct S {
// @size(5) a : f32; // @size(5) a : f32;
// @align(1) b : f32; // @align(1) b : f32;
@ -39,13 +39,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember)
Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(1_i)}), Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(1_i)}),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::StorageClass::kStorage, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::AddressSpace::kStorage, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(34:56 error: the offset of a struct member of type 'f32' in storage class 'storage' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting @align(4) on this member R"(34:56 error: the offset of a struct member of type 'f32' in address space 'storage' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting @align(4) on this member
12:34 note: see layout of struct: 12:34 note: see layout of struct:
/* align(4) size(12) */ struct S { /* align(4) size(12) */ struct S {
/* offset(0) align(4) size( 5) */ a : f32; /* offset(0) align(4) size( 5) */ a : f32;
@ -55,7 +55,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember)
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember_SuggestedFix) { TEST_F(ResolverAddressSpaceLayoutValidationTest, StorageBuffer_UnalignedMember_SuggestedFix) {
// struct S { // struct S {
// @size(5) a : f32; // @size(5) a : f32;
// @align(4) b : f32; // @align(4) b : f32;
@ -69,14 +69,14 @@ TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember_S
Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(4_i)}), Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(4_i)}),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::StorageClass::kStorage, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::AddressSpace::kStorage, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
// Detect unaligned struct member for uniform buffers // Detect unaligned struct member for uniform buffers
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_Struct) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_UnalignedMember_Struct) {
// struct Inner { // struct Inner {
// scalar : i32; // scalar : i32;
// }; // };
@ -100,13 +100,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_S
Member(Source{{56, 78}}, "inner", ty.type_name("Inner")), Member(Source{{56, 78}}, "inner", ty.type_name("Inner")),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: the offset of a struct member of type 'Inner' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member R"(56:78 error: the offset of a struct member of type 'Inner' in address space 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member
34:56 note: see layout of struct: 34:56 note: see layout of struct:
/* align(4) size(8) */ struct Outer { /* align(4) size(8) */ struct Outer {
/* offset(0) align(4) size(4) */ scalar : f32; /* offset(0) align(4) size(4) */ scalar : f32;
@ -119,7 +119,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_S
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_UnalignedMember_Struct_SuggestedFix) { UniformBuffer_UnalignedMember_Struct_SuggestedFix) {
// struct Inner { // struct Inner {
// scalar : i32; // scalar : i32;
@ -145,14 +145,14 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
utils::Vector{MemberAlign(16_i)}), utils::Vector{MemberAlign(16_i)}),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
// Detect unaligned array member for uniform buffers // Detect unaligned array member for uniform buffers
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_Array) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_UnalignedMember_Array) {
// type Inner = @stride(16) array<f32, 10u>; // type Inner = @stride(16) array<f32, 10u>;
// //
// struct Outer { // struct Outer {
@ -170,13 +170,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
Member(Source{{56, 78}}, "inner", ty.type_name("Inner")), Member(Source{{56, 78}}, "inner", ty.type_name("Inner")),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: the offset of a struct member of type '@stride(16) array<f32, 10>' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member R"(56:78 error: the offset of a struct member of type '@stride(16) array<f32, 10>' in address space 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member
12:34 note: see layout of struct: 12:34 note: see layout of struct:
/* align(4) size(164) */ struct Outer { /* align(4) size(164) */ struct Outer {
/* offset( 0) align(4) size( 4) */ scalar : f32; /* offset( 0) align(4) size( 4) */ scalar : f32;
@ -185,7 +185,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_Array_SuggestedFix) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_UnalignedMember_Array_SuggestedFix) {
// type Inner = @stride(16) array<f32, 10u>; // type Inner = @stride(16) array<f32, 10u>;
// //
// struct Outer { // struct Outer {
@ -204,7 +204,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
utils::Vector{MemberAlign(16_i)}), utils::Vector{MemberAlign(16_i)}),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -212,7 +212,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
// Detect uniform buffers with byte offset between 2 members that is not a // Detect uniform buffers with byte offset between 2 members that is not a
// multiple of 16 bytes // multiple of 16 bytes
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotMultipleOf16) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_MembersOffsetNotMultipleOf16) {
// struct Inner { // struct Inner {
// @align(1) @size(5) scalar : i32; // @align(1) @size(5) scalar : i32;
// }; // };
@ -236,7 +236,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotM
Member(Source{{78, 90}}, "scalar", ty.i32()), Member(Source{{78, 90}}, "scalar", ty.i32()),
}); });
GlobalVar(Source{{22, 24}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{22, 24}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -257,7 +257,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotM
} }
// See https://crbug.com/tint/1344 // See https://crbug.com/tint/1344
TEST_F(ResolverStorageClassLayoutValidationTest, TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_MembersOffsetNotMultipleOf16_InnerMoreMembersThanOuter) { UniformBuffer_MembersOffsetNotMultipleOf16_InnerMoreMembersThanOuter) {
// struct Inner { // struct Inner {
// a : i32; // a : i32;
@ -288,7 +288,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
Member(Source{{78, 90}}, "scalar", ty.i32()), Member(Source{{78, 90}}, "scalar", ty.i32()),
}); });
GlobalVar(Source{{22, 24}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{22, 24}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -311,7 +311,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
22:24 note: see declaration of variable)"); 22:24 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_MembersOffsetNotMultipleOf16_SuggestedFix) { UniformBuffer_MembersOffsetNotMultipleOf16_SuggestedFix) {
// struct Inner { // struct Inner {
// @align(1) @size(5) scalar : i32; // @align(1) @size(5) scalar : i32;
@ -336,7 +336,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
Member(Source{{78, 90}}, "scalar", ty.i32(), utils::Vector{MemberAlign(16_i)}), Member(Source{{78, 90}}, "scalar", ty.i32(), utils::Vector{MemberAlign(16_i)}),
}); });
GlobalVar(Source{{22, 34}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{22, 34}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -344,7 +344,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
// Make sure that this doesn't fail validation because vec3's align is 16, but // Make sure that this doesn't fail validation because vec3's align is 16, but
// size is 12. 's' should be at offset 12, which is okay here. // size is 12. 's' should be at offset 12, which is okay here.
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_Vec3MemberOffset_NoFail) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_Vec3MemberOffset_NoFail) {
// struct ScalarPackedAtEndOfVec3 { // struct ScalarPackedAtEndOfVec3 {
// v : vec3<f32>; // v : vec3<f32>;
// s : f32; // s : f32;
@ -358,13 +358,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_Vec3MemberOffset_
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("ScalarPackedAtEndOfVec3"), GlobalVar(Source{{78, 90}}, "a", ty.type_name("ScalarPackedAtEndOfVec3"),
ast::StorageClass::kUniform, Group(0_a), Binding(0_a)); ast::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
// Detect array stride must be a multiple of 16 bytes for uniform buffers // Detect array stride must be a multiple of 16 bytes for uniform buffers
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_Scalar) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_Scalar) {
// type Inner = array<f32, 10u>; // type Inner = array<f32, 10u>;
// //
// struct Outer { // struct Outer {
@ -383,7 +383,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
Member("scalar", ty.i32()), Member("scalar", ty.i32()),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -398,7 +398,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_Vector) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_Vector) {
// type Inner = array<vec2<f32>, 10u>; // type Inner = array<vec2<f32>, 10u>;
// //
// struct Outer { // struct Outer {
@ -417,7 +417,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
Member("scalar", ty.i32()), Member("scalar", ty.i32()),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -433,7 +433,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_Struct) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_Struct) {
// struct ArrayElem { // struct ArrayElem {
// a : f32; // a : f32;
// b : i32; // b : i32;
@ -460,7 +460,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
Member("scalar", ty.i32()), Member("scalar", ty.i32()),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -475,11 +475,11 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_TopLevelArray) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_TopLevelArray) {
// @group(0) @binding(0) // @group(0) @binding(0)
// var<uniform> a : array<f32, 4u>; // var<uniform> a : array<f32, 4u>;
GlobalVar(Source{{78, 90}}, "a", ty.array(Source{{34, 56}}, ty.f32(), 4_u), GlobalVar(Source{{78, 90}}, "a", ty.array(Source{{34, 56}}, ty.f32(), 4_u),
ast::StorageClass::kUniform, Group(0_a), Binding(0_a)); ast::AddressSpace::kUniform, Group(0_a), Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
@ -487,7 +487,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
R"(34:56 error: uniform storage requires that array elements be aligned to 16 bytes, but array element alignment is currently 4. Consider using a vector or struct as the element type instead.)"); R"(34:56 error: uniform storage requires that array elements be aligned to 16 bytes, but array element alignment is currently 4. Consider using a vector or struct as the element type instead.)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_NestedArray) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_NestedArray) {
// struct Outer { // struct Outer {
// inner : array<array<f32, 4u>, 4u> // inner : array<array<f32, 4u>, 4u>
// }; // };
@ -500,7 +500,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
Member("inner", ty.array(Source{{34, 56}}, ty.array(ty.f32(), 4_u), 4_u)), Member("inner", ty.array(Source{{34, 56}}, ty.array(ty.f32(), 4_u), 4_u)),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -514,7 +514,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_SuggestedFix) { TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_SuggestedFix) {
// type Inner = @stride(16) array<f32, 10u>; // type Inner = @stride(16) array<f32, 10u>;
// //
// struct Outer { // struct Outer {
@ -533,14 +533,14 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
Member("scalar", ty.i32()), Member("scalar", ty.i32()),
}); });
GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::StorageClass::kUniform, Group(0_a), GlobalVar(Source{{78, 90}}, "a", ty.type_name("Outer"), ast::AddressSpace::kUniform, Group(0_a),
Binding(0_a)); Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
// Detect unaligned member for push constants buffers // Detect unaligned member for push constants buffers
TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) { TEST_F(ResolverAddressSpaceLayoutValidationTest, PushConstant_UnalignedMember) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// struct S { // struct S {
// @size(5) a : f32; // @size(5) a : f32;
@ -552,12 +552,12 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) {
Source{{12, 34}}, "S", Source{{12, 34}}, "S",
utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}), utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}),
Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(1_i)})}); Member(Source{{34, 56}}, "b", ty.f32(), utils::Vector{MemberAlign(1_i)})});
GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::StorageClass::kPushConstant); GlobalVar(Source{{78, 90}}, "a", ty.type_name("S"), ast::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(34:56 error: the offset of a struct member of type 'f32' in storage class 'push_constant' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting @align(4) on this member R"(34:56 error: the offset of a struct member of type 'f32' in address space 'push_constant' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting @align(4) on this member
12:34 note: see layout of struct: 12:34 note: see layout of struct:
/* align(4) size(12) */ struct S { /* align(4) size(12) */ struct S {
/* offset(0) align(4) size( 5) */ a : f32; /* offset(0) align(4) size( 5) */ a : f32;
@ -567,7 +567,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) {
78:90 note: see declaration of variable)"); 78:90 note: see declaration of variable)");
} }
TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_Aligned) { TEST_F(ResolverAddressSpaceLayoutValidationTest, PushConstant_Aligned) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// struct S { // struct S {
// @size(5) a : f32; // @size(5) a : f32;
@ -577,7 +577,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_Aligned) {
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}), Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}),
Member("b", ty.f32(), utils::Vector{MemberAlign(4_i)})}); Member("b", ty.f32(), utils::Vector{MemberAlign(4_i)})});
GlobalVar("a", ty.type_name("S"), ast::StorageClass::kPushConstant); GlobalVar("a", ty.type_name("S"), ast::AddressSpace::kPushConstant);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }

View File

@ -25,169 +25,169 @@ namespace {
using ::testing::HasSubstr; using ::testing::HasSubstr;
using ResolverStorageClassValidationTest = ResolverTest; using ResolverAddressSpaceValidationTest = ResolverTest;
TEST_F(ResolverStorageClassValidationTest, GlobalVariableNoStorageClass_Fail) { TEST_F(ResolverAddressSpaceValidationTest, GlobalVariableNoAddressSpace_Fail) {
// var g : f32; // var g : f32;
GlobalVar(Source{{12, 34}}, "g", ty.f32()); GlobalVar(Source{{12, 34}}, "g", ty.f32());
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: module-scope 'var' declaration must have a storage class"); "12:34 error: module-scope 'var' declaration must have a address space");
} }
TEST_F(ResolverStorageClassValidationTest, GlobalVariableFunctionStorageClass_Fail) { TEST_F(ResolverAddressSpaceValidationTest, GlobalVariableFunctionAddressSpace_Fail) {
// var<function> g : f32; // var<function> g : f32;
GlobalVar(Source{{12, 34}}, "g", ty.f32(), ast::StorageClass::kFunction); GlobalVar(Source{{12, 34}}, "g", ty.f32(), ast::AddressSpace::kFunction);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: module-scope 'var' must not use storage class 'function'"); "12:34 error: module-scope 'var' must not use address space 'function'");
} }
TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArray) { TEST_F(ResolverAddressSpaceValidationTest, Private_RuntimeArray) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::StorageClass::kPrivate); GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
12:34 note: while instantiating 'var' v)"); 12:34 note: while instantiating 'var' v)");
} }
TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArrayInStruct) { TEST_F(ResolverAddressSpaceValidationTest, Private_RuntimeArrayInStruct) {
auto* s = Structure("S", utils::Vector{Member("m", ty.array(ty.i32()))}); auto* s = Structure("S", utils::Vector{Member("m", ty.array(ty.i32()))});
GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kPrivate); GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
note: while analysing structure member S.m note: while analysing structure member S.m
12:34 note: while instantiating 'var' v)"); 12:34 note: while instantiating 'var' v)");
} }
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArray) { TEST_F(ResolverAddressSpaceValidationTest, Workgroup_RuntimeArray) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::StorageClass::kWorkgroup); GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
12:34 note: while instantiating 'var' v)"); 12:34 note: while instantiating 'var' v)");
} }
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArrayInStruct) { TEST_F(ResolverAddressSpaceValidationTest, Workgroup_RuntimeArrayInStruct) {
auto* s = Structure("S", utils::Vector{Member("m", ty.array(ty.i32()))}); auto* s = Structure("S", utils::Vector{Member("m", ty.array(ty.i32()))});
GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kWorkgroup); GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
note: while analysing structure member S.m note: while analysing structure member S.m
12:34 note: while instantiating 'var' v)"); 12:34 note: while instantiating 'var' v)");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferBool) {
// var<storage> g : bool; // var<storage> g : bool;
GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kStorage, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::AddressSpace::kStorage, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'storage' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferBoolAlias) { TEST_F(ResolverAddressSpaceValidationTest, 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_());
GlobalVar(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kStorage, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.Of(a), ast::AddressSpace::kStorage, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'storage' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
// F16 types in storage and uniform buffer is not implemented yet. // F16 types in storage and uniform buffer is not implemented yet.
// TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported. // TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported.
TEST_F(ResolverStorageClassValidationTest, StorageBufferF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16_TemporallyBan) {
// var<storage> g : f16; // var<storage> g : f16;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("g", ty.f16(Source{{56, 78}}), ast::StorageClass::kStorage, Binding(0_a), Group(0_a)); GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kStorage, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'storage' storage class is not " "56:78 error: using f16 types in 'storage' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferF16Alias_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16Alias_TemporallyBan) {
// type a = f16; // type a = f16;
// var<storage, read> g : a; // var<storage, read> g : a;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* a = Alias("a", ty.f16()); auto* a = Alias("a", ty.f16());
GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::StorageClass::kStorage, GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::AddressSpace::kStorage,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'storage' storage class is not " "56:78 error: using f16 types in 'storage' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferVectorF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF16_TemporallyBan) {
// var<storage> g : vec4<f16>; // var<storage> g : vec4<f16>;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::StorageClass::kStorage, GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::AddressSpace::kStorage,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'storage' storage class is not " "56:78 error: using f16 types in 'storage' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferArrayF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF16_TemporallyBan) {
// struct S { a : f16 }; // struct S { a : f16 };
// var<storage, read> g : array<S, 3u>; // var<storage, read> g : array<S, 3u>;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* s = Structure("S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}))}); auto* s = Structure("S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}))});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar("g", a, ast::StorageClass::kStorage, ast::Access::kRead, Binding(0_a), Group(0_a)); GlobalVar("g", a, ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'storage' storage " EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'storage' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferStructF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructF16_TemporallyBan) {
// struct S { x : f16 }; // struct S { x : f16 };
// var<storage, read> g : S; // var<storage, read> g : S;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))}); auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
GlobalVar("g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, Binding(0_a), GlobalVar("g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' storage " EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferNoErrorStructF16Aliases_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructF16Aliases_TemporallyBan) {
// struct S { x : f16 }; // struct S { x : f16 };
// type a1 = S; // type a1 = S;
// var<storage, read> g : a1; // var<storage, read> g : a1;
@ -196,84 +196,84 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoErrorStructF16Aliases_
auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))}); auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
auto* a1 = Alias("a1", ty.Of(s)); auto* a1 = Alias("a1", ty.Of(s));
auto* a2 = Alias("a2", ty.Of(a1)); auto* a2 = Alias("a2", ty.Of(a1));
GlobalVar("g", ty.Of(a2), ast::StorageClass::kStorage, ast::Access::kRead, Binding(0_a), GlobalVar("g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' storage " EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferPointer) {
// var<storage> g : ptr<private, f32>; // var<storage> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate), GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::StorageClass::kStorage, Binding(0_a), Group(0_a)); ast::AddressSpace::kStorage, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'storage' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferIntScalar) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferIntScalar) {
// var<storage> g : i32; // var<storage> g : i32;
GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kStorage, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::AddressSpace::kStorage, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferVectorF32) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF32) {
// var<storage> g : vec4<f32>; // var<storage> g : vec4<f32>;
GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::StorageClass::kStorage, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::AddressSpace::kStorage, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferArrayF32) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF32) {
// var<storage, read> g : array<S, 3u>; // var<storage, read> g : array<S, 3u>;
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", a, ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, NotStorage_AccessMode) { TEST_F(ResolverAddressSpaceValidationTest, NotStorage_AccessMode) {
// var<private, read> g : a; // var<private, read> g : a;
GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kPrivate, ast::Access::kRead); GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::AddressSpace::kPrivate, ast::Access::kRead);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: only variables in <storage> storage class may declare an access mode)"); R"(56:78 error: only variables in <storage> address space may declare an access mode)");
} }
TEST_F(ResolverStorageClassValidationTest, Storage_ReadAccessMode) { TEST_F(ResolverAddressSpaceValidationTest, Storage_ReadAccessMode) {
// @group(0) @binding(0) var<storage, read> a : i32; // @group(0) @binding(0) var<storage, read> a : i32;
GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, Storage_ReadWriteAccessMode) { TEST_F(ResolverAddressSpaceValidationTest, Storage_ReadWriteAccessMode) {
// @group(0) @binding(0) var<storage, read_write> a : i32; // @group(0) @binding(0) var<storage, read_write> a : i32;
GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::StorageClass::kStorage, ast::Access::kReadWrite, GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, Storage_WriteAccessMode) { TEST_F(ResolverAddressSpaceValidationTest, Storage_WriteAccessMode) {
// @group(0) @binding(0) var<storage, read_write> a : i32; // @group(0) @binding(0) var<storage, read_write> a : i32;
GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::StorageClass::kStorage, ast::Access::kWrite, GlobalVar(Source{{56, 78}}, "a", ty.i32(), ast::AddressSpace::kStorage, ast::Access::kWrite,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
@ -282,117 +282,117 @@ TEST_F(ResolverStorageClassValidationTest, Storage_WriteAccessMode) {
R"(56:78 error: access mode 'write' is not valid for the 'storage' address space)"); R"(56:78 error: access mode 'write' is not valid for the 'storage' address space)");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferStructI32) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructI32) {
// struct S { x : i32 }; // struct S { x : i32 };
// var<storage, read> g : S; // var<storage, read> g : S;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()); ASSERT_TRUE(r()->Resolve());
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferNoErrorStructI32Aliases) { TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructI32Aliases) {
// struct S { x : i32 }; // struct S { x : i32 };
// type a1 = S; // type a1 = S;
// var<storage, read> g : a1; // var<storage, read> g : a1;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
auto* a1 = Alias("a1", ty.Of(s)); auto* a1 = Alias("a1", ty.Of(s));
auto* a2 = Alias("a2", ty.Of(a1)); auto* a2 = Alias("a2", ty.Of(a1));
GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()); ASSERT_TRUE(r()->Resolve());
} }
TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) { TEST_F(ResolverAddressSpaceValidationTest, UniformBuffer_Struct_Runtime) {
// struct S { m: array<f32>; }; // struct S { m: array<f32>; };
// @group(0) @binding(0) var<uniform, > svar : S; // @group(0) @binding(0) var<uniform, > svar : S;
auto* s = Structure(Source{{12, 34}}, "S", utils::Vector{Member("m", ty.array<i32>())}); auto* s = Structure(Source{{12, 34}}, "S", utils::Vector{Member("m", ty.array<i32>())});
GlobalVar(Source{{56, 78}}, "svar", ty.Of(s), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "svar", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class R"(56:78 error: runtime-sized arrays can only be used in the <storage> address space
note: while analysing structure member S.m note: while analysing structure member S.m
56:78 note: while instantiating 'var' svar)"); 56:78 note: while instantiating 'var' svar)");
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferBool) {
// var<uniform> g : bool; // var<uniform> g : bool;
GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'uniform' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'uniform' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferBoolAlias) { TEST_F(ResolverAddressSpaceValidationTest, 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_());
GlobalVar(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.Of(a), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'uniform' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'uniform' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
// F16 types in storage and uniform buffer is not implemented yet. // F16 types in storage and uniform buffer is not implemented yet.
// TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported. // TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported.
TEST_F(ResolverStorageClassValidationTest, UniformBufferF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16_TemporallyBan) {
// var<uniform> g : f16; // var<uniform> g : f16;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("g", ty.f16(Source{{56, 78}}), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'uniform' storage class is not " "56:78 error: using f16 types in 'uniform' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferF16Alias_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16Alias_TemporallyBan) {
// type a = f16; // type a = f16;
// var<uniform> g : a; // var<uniform> g : a;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* a = Alias("a", ty.f16()); auto* a = Alias("a", ty.f16());
GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::StorageClass::kUniform, GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::AddressSpace::kUniform,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'uniform' storage class is not " "56:78 error: using f16 types in 'uniform' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferVectorF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF16_TemporallyBan) {
// var<uniform> g : vec4<f16>; // var<uniform> g : vec4<f16>;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::StorageClass::kUniform, GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::AddressSpace::kUniform,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' storage " EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF16_TemporallyBan) {
// struct S { // struct S {
// @size(16) f : f16; // @size(16) f : f16;
// } // }
@ -402,29 +402,29 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF16_TemporallyBan)
auto* s = Structure( auto* s = Structure(
"S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}), utils::Vector{MemberSize(16_a)})}); "S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}), utils::Vector{MemberSize(16_a)})});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar("g", a, ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("g", a, ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' storage " EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructF16_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16_TemporallyBan) {
// struct S { x : f16 }; // struct S { x : f16 };
// var<uniform> g : S; // var<uniform> g : S;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))}); auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
GlobalVar("g", ty.Of(s), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("g", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' storage " EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructF16Aliases_TemporallyBan) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16Aliases_TemporallyBan) {
// struct S { x : f16 }; // struct S { x : f16 };
// type a1 = S; // type a1 = S;
// var<uniform> g : a1; // var<uniform> g : a1;
@ -432,159 +432,159 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferStructF16Aliases_Tempora
auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))}); auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
auto* a1 = Alias("a1", ty.Of(s)); auto* a1 = Alias("a1", ty.Of(s));
GlobalVar("g", ty.Of(a1), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("g", ty.Of(a1), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' storage " EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
"class is not implemented yet")); "space is not implemented yet"));
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferPointer) {
// var<uniform> g : ptr<private, f32>; // var<uniform> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate), GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in storage class 'uniform' as it is non-host-shareable R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'uniform' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferIntScalar) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferIntScalar) {
// var<uniform> g : i32; // var<uniform> g : i32;
GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferVectorF32) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF32) {
// var<uniform> g : vec4<f32>; // var<uniform> g : vec4<f32>;
GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF32) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF32) {
// struct S { // struct S {
// @size(16) f : f32; // @size(16) f : f32;
// } // }
// var<uniform> g : array<S, 3u>; // var<uniform> g : array<S, 3u>;
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(16_a)})}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(16_a)})});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar(Source{{56, 78}}, "g", a, ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructI32) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructI32) {
// struct S { x : i32 }; // struct S { x : i32 };
// var<uniform> g : S; // var<uniform> g : S;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructI32Aliases) { TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructI32Aliases) {
// struct S { x : i32 }; // struct S { x : i32 };
// type a1 = S; // type a1 = S;
// var<uniform> g : a1; // var<uniform> g : a1;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
auto* a1 = Alias("a1", ty.Of(s)); auto* a1 = Alias("a1", ty.Of(s));
GlobalVar(Source{{56, 78}}, "g", ty.Of(a1), ast::StorageClass::kUniform, Binding(0_a), GlobalVar(Source{{56, 78}}, "g", ty.Of(a1), ast::AddressSpace::kUniform, Binding(0_a),
Group(0_a)); Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantBool) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantBool) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> g : bool; // var<push_constant> g : bool;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kPushConstant); GlobalVar(Source{{56, 78}}, "g", ty.bool_(), ast::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'push_constant' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'push_constant' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantF16) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantF16) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// enable f16; // enable f16;
// var<push_constant> g : f16; // var<push_constant> g : f16;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("g", ty.f16(Source{{56, 78}}), ast::StorageClass::kPushConstant); GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"56:78 error: using f16 types in 'push_constant' storage class is not " "56:78 error: using f16 types in 'push_constant' address space is not "
"implemented yet"); "implemented yet");
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantPointer) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantPointer) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> g : ptr<private, f32>; // var<push_constant> g : ptr<private, f32>;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate), GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::StorageClass::kPushConstant); ast::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in storage class 'push_constant' as it is non-host-shareable R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in address space 'push_constant' as it is non-host-shareable
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantIntScalar) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantIntScalar) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> g : i32; // var<push_constant> g : i32;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("g", ty.i32(), ast::StorageClass::kPushConstant); GlobalVar("g", ty.i32(), ast::AddressSpace::kPushConstant);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantVectorF32) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantVectorF32) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> g : vec4<f32>; // var<push_constant> g : vec4<f32>;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("g", ty.vec4<f32>(), ast::StorageClass::kPushConstant); GlobalVar("g", ty.vec4<f32>(), ast::AddressSpace::kPushConstant);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantArrayF32) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantArrayF32) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// struct S { a : f32} // struct S { a : f32}
// var<push_constant> g : array<S, 3u>; // var<push_constant> g : array<S, 3u>;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar("g", a, ast::StorageClass::kPushConstant); GlobalVar("g", a, ast::AddressSpace::kPushConstant);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverStorageClassValidationTest, PushConstantWithInitializer) { TEST_F(ResolverAddressSpaceValidationTest, PushConstantWithInitializer) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> a : u32 = 0u; // var<push_constant> a : u32 = 0u;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{1u, 2u}}, "a", ty.u32(), ast::StorageClass::kPushConstant, GlobalVar(Source{{1u, 2u}}, "a", ty.u32(), ast::AddressSpace::kPushConstant,
Expr(Source{{3u, 4u}}, u32(0))); Expr(Source{{3u, 4u}}, u32(0)));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(1:2 error: var of storage class 'push_constant' cannot have an initializer. var initializers are only supported for the storage classes 'private' and 'function')"); R"(1:2 error: var of address space 'push_constant' cannot have an initializer. var initializers are only supported for the address spacees 'private' and 'function')");
} }
} // namespace } // namespace

View File

@ -27,7 +27,7 @@ namespace {
using ResolverIndexAccessorTest = ResolverTest; using ResolverIndexAccessorTest = ResolverTest;
TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) { TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
GlobalVar("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.mat2x3<f32>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 1_f)); auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 1_f));
WrapInFunction(acc); WrapInFunction(acc);
@ -36,7 +36,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
} }
TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_Ref) { TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_Ref) {
GlobalVar("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.mat2x3<f32>(), ast::AddressSpace::kPrivate);
auto* idx = Var("idx", ty.i32(), Construct(ty.i32())); auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
auto* acc = IndexAccessor("my_var", idx); auto* acc = IndexAccessor("my_var", idx);
WrapInFunction(Decl(idx), acc); WrapInFunction(Decl(idx), acc);
@ -50,7 +50,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_Ref) {
} }
TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions_Dynamic_Ref) { TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions_Dynamic_Ref) {
GlobalVar("my_var", ty.mat4x4<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.mat4x4<f32>(), ast::AddressSpace::kPrivate);
auto* idx = Var("idx", ty.u32(), Expr(3_u)); auto* idx = Var("idx", ty.u32(), Expr(3_u));
auto* idy = Var("idy", ty.u32(), Expr(2_u)); auto* idy = Var("idy", ty.u32(), Expr(2_u));
auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy); auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy);
@ -100,7 +100,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_BothDimension_Dynamic) {
} }
TEST_F(ResolverIndexAccessorTest, Matrix) { TEST_F(ResolverIndexAccessorTest, Matrix) {
GlobalVar("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.mat2x3<f32>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 1_i); auto* acc = IndexAccessor("my_var", 1_i);
WrapInFunction(acc); WrapInFunction(acc);
@ -121,7 +121,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix) {
} }
TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) { TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) {
GlobalVar("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.mat2x3<f32>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor(IndexAccessor("my_var", 0_i), 1_i); auto* acc = IndexAccessor(IndexAccessor("my_var", 0_i), 1_i);
WrapInFunction(acc); WrapInFunction(acc);
@ -141,7 +141,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) {
} }
TEST_F(ResolverIndexAccessorTest, Vector_F32) { TEST_F(ResolverIndexAccessorTest, Vector_F32) {
GlobalVar("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 2_f)); auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 2_f));
WrapInFunction(acc); WrapInFunction(acc);
@ -150,7 +150,7 @@ TEST_F(ResolverIndexAccessorTest, Vector_F32) {
} }
TEST_F(ResolverIndexAccessorTest, Vector_Dynamic_Ref) { TEST_F(ResolverIndexAccessorTest, Vector_Dynamic_Ref) {
GlobalVar("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* idx = Var("idx", ty.i32(), Expr(2_i)); auto* idx = Var("idx", ty.i32(), Expr(2_i));
auto* acc = IndexAccessor("my_var", idx); auto* acc = IndexAccessor("my_var", idx);
WrapInFunction(Decl(idx), acc); WrapInFunction(Decl(idx), acc);
@ -173,7 +173,7 @@ TEST_F(ResolverIndexAccessorTest, Vector_Dynamic) {
} }
TEST_F(ResolverIndexAccessorTest, Vector) { TEST_F(ResolverIndexAccessorTest, Vector) {
GlobalVar("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 2_i); auto* acc = IndexAccessor("my_var", 2_i);
WrapInFunction(acc); WrapInFunction(acc);
@ -193,7 +193,7 @@ TEST_F(ResolverIndexAccessorTest, Vector) {
} }
TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) { TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) {
GlobalVar("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.array<f32, 3>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 2_i); auto* acc = IndexAccessor("my_var", 2_i);
WrapInFunction(acc); WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -209,7 +209,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) {
} }
TEST_F(ResolverIndexAccessorTest, Array_Literal_u32) { TEST_F(ResolverIndexAccessorTest, Array_Literal_u32) {
GlobalVar("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.array<f32, 3>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 2_u); auto* acc = IndexAccessor("my_var", 2_u);
WrapInFunction(acc); WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -225,7 +225,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_u32) {
} }
TEST_F(ResolverIndexAccessorTest, Array_Literal_AInt) { TEST_F(ResolverIndexAccessorTest, Array_Literal_AInt) {
GlobalVar("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.array<f32, 3>(), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 2_a); auto* acc = IndexAccessor("my_var", 2_a);
WrapInFunction(acc); WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -243,7 +243,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_AInt) {
TEST_F(ResolverIndexAccessorTest, Alias_Array) { TEST_F(ResolverIndexAccessorTest, Alias_Array) {
auto* aary = Alias("myarrty", ty.array<f32, 3>()); auto* aary = Alias("myarrty", ty.array<f32, 3>());
GlobalVar("my_var", ty.Of(aary), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.Of(aary), ast::AddressSpace::kPrivate);
auto* acc = IndexAccessor("my_var", 2_i); auto* acc = IndexAccessor("my_var", 2_i);
WrapInFunction(acc); WrapInFunction(acc);
@ -337,7 +337,7 @@ TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncGoodParent) {
// let x: f32 = (*p)[idx]; // let x: f32 = (*p)[idx];
// return x; // return x;
// } // }
auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction)); auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::AddressSpace::kFunction));
auto* idx = Let("idx", ty.u32(), Construct(ty.u32())); auto* idx = Let("idx", ty.u32(), Construct(ty.u32()));
auto* star_p = Deref(p); auto* star_p = Deref(p);
auto* acc = IndexAccessor(Source{{12, 34}}, star_p, idx); auto* acc = IndexAccessor(Source{{12, 34}}, star_p, idx);
@ -358,7 +358,7 @@ TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncBadParent) {
// let x: f32 = *p[idx]; // let x: f32 = *p[idx];
// return x; // return x;
// } // }
auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction)); auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::AddressSpace::kFunction));
auto* idx = Let("idx", ty.u32(), Construct(ty.u32())); auto* idx = Let("idx", ty.u32(), Construct(ty.u32()));
auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx); auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
auto* star_p = Deref(accessor_expr); auto* star_p = Deref(accessor_expr);

View File

@ -32,7 +32,7 @@ TEST_F(ResolverAssignmentValidationTest, ReadOnlyBuffer) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("m", ty.i32()), Member("m", ty.i32()),
}); });
GlobalVar(Source{{12, 34}}, "a", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{12, 34}}, "a", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("a", "m"), 1_i)); WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("a", "m"), 1_i));
@ -192,7 +192,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignThroughPointer_Pass) {
// var a : i32; // var a : i32;
// let b : ptr<function,i32> = &a; // let b : ptr<function,i32> = &a;
// *b = 2i; // *b = 2i;
const auto func = ast::StorageClass::kFunction; const auto func = ast::AddressSpace::kFunction;
WrapInFunction(Var("a", ty.i32(), func, Expr(2_i)), // WrapInFunction(Var("a", ty.i32(), func, Expr(2_i)), //
Let("b", ty.pointer<i32>(func), AddressOf(Expr("a"))), // Let("b", ty.pointer<i32>(func), AddressOf(Expr("a"))), //
Assign(Deref("b"), 2_i)); Assign(Deref("b"), 2_i));
@ -204,7 +204,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignMaterializedThroughPointer_Pass)
// var a : i32; // var a : i32;
// let b : ptr<function,i32> = &a; // let b : ptr<function,i32> = &a;
// *b = 2; // *b = 2;
const auto func = ast::StorageClass::kFunction; const auto func = ast::AddressSpace::kFunction;
auto* var_a = Var("a", ty.i32(), func, Expr(2_i)); auto* var_a = Var("a", ty.i32(), func, Expr(2_i));
auto* var_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("a"))); auto* var_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b, Assign(Deref("b"), 2_a)); WrapInFunction(var_a, var_b, Assign(Deref("b"), 2_a));
@ -251,7 +251,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_Atomic) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("a", ty.atomic(ty.i32())), Member("a", ty.atomic(ty.i32())),
}); });
GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("v", "a"), MemberAccessor("v", "a"))); WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("v", "a"), MemberAccessor("v", "a")));
@ -268,7 +268,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_RuntimeArray) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("a", ty.array(ty.f32())), Member("a", ty.array(ty.f32())),
}); });
GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, GlobalVar(Source{{12, 34}}, "v", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("v", "a"), MemberAccessor("v", "a"))); WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("v", "a"), MemberAccessor("v", "a")));
@ -288,7 +288,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_NonConstructibleStruct_Fa
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("arr", ty.array<i32>()), Member("arr", ty.array<i32>()),
}); });
GlobalVar("s", ty.Of(s), ast::StorageClass::kStorage, Group(0_a), Binding(0_a)); GlobalVar("s", ty.Of(s), ast::AddressSpace::kStorage, Group(0_a), Binding(0_a));
WrapInFunction(Assign(Phony(), Expr(Source{{12, 34}}, "s"))); WrapInFunction(Assign(Phony(), Expr(Source{{12, 34}}, "s")));
@ -310,7 +310,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_DynamicArray_Fail) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("arr", ty.array<i32>()), Member("arr", ty.array<i32>()),
}); });
GlobalVar("s", ty.Of(s), ast::StorageClass::kStorage, Group(0_a), Binding(0_a)); GlobalVar("s", ty.Of(s), ast::AddressSpace::kStorage, Group(0_a), Binding(0_a));
WrapInFunction(Assign(Phony(), MemberAccessor(Source{{12, 34}}, "s", "arr"))); WrapInFunction(Assign(Phony(), MemberAccessor(Source{{12, 34}}, "s", "arr")));
@ -363,9 +363,9 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_Pass) {
GlobalVar("tex", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), Group(0_a), GlobalVar("tex", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), Group(0_a),
Binding(0_a)); Binding(0_a));
GlobalVar("smp", ty.sampler(ast::SamplerKind::kSampler), Group(0_a), Binding(1_a)); GlobalVar("smp", ty.sampler(ast::SamplerKind::kSampler), Group(0_a), Binding(1_a));
GlobalVar("u", ty.Of(U), ast::StorageClass::kUniform, Group(0_a), Binding(2_a)); GlobalVar("u", ty.Of(U), ast::AddressSpace::kUniform, Group(0_a), Binding(2_a));
GlobalVar("s", ty.Of(S), ast::StorageClass::kStorage, Group(0_a), Binding(3_a)); GlobalVar("s", ty.Of(S), ast::AddressSpace::kStorage, Group(0_a), Binding(3_a));
GlobalVar("wg", ty.array<f32, 10>(), ast::StorageClass::kWorkgroup); GlobalVar("wg", ty.array<f32, 10>(), ast::AddressSpace::kWorkgroup);
WrapInFunction(Assign(Phony(), 1_i), // WrapInFunction(Assign(Phony(), 1_i), //
Assign(Phony(), 2_u), // Assign(Phony(), 2_u), //

View File

@ -27,7 +27,7 @@ using namespace tint::number_suffixes; // NOLINT
struct ResolverAtomicTest : public resolver::TestHelper, public testing::Test {}; struct ResolverAtomicTest : public resolver::TestHelper, public testing::Test {};
TEST_F(ResolverAtomicTest, GlobalWorkgroupI32) { TEST_F(ResolverAtomicTest, GlobalWorkgroupI32) {
auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kWorkgroup); auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
@ -37,7 +37,7 @@ TEST_F(ResolverAtomicTest, GlobalWorkgroupI32) {
} }
TEST_F(ResolverAtomicTest, GlobalWorkgroupU32) { TEST_F(ResolverAtomicTest, GlobalWorkgroupU32) {
auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.u32()), ast::StorageClass::kWorkgroup); auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.u32()), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
@ -48,7 +48,7 @@ TEST_F(ResolverAtomicTest, GlobalWorkgroupU32) {
TEST_F(ResolverAtomicTest, GlobalStorageStruct) { TEST_F(ResolverAtomicTest, GlobalStorageStruct) {
auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))}); auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))});
auto* g = GlobalVar("g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, auto* g = GlobalVar("g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -26,64 +26,64 @@ namespace {
struct ResolverAtomicValidationTest : public resolver::TestHelper, public testing::Test {}; struct ResolverAtomicValidationTest : public resolver::TestHelper, public testing::Test {};
TEST_F(ResolverAtomicValidationTest, StorageClass_WorkGroup) { TEST_F(ResolverAtomicValidationTest, AddressSpace_WorkGroup) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kWorkgroup); GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()); EXPECT_TRUE(r()->Resolve());
} }
TEST_F(ResolverAtomicValidationTest, StorageClass_Storage) { TEST_F(ResolverAtomicValidationTest, AddressSpace_Storage) {
GlobalVar("g", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kStorage, GlobalVar("g", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kStorage,
ast::Access::kReadWrite, Group(0_a), Binding(0_a)); ast::Access::kReadWrite, Group(0_a), Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverAtomicValidationTest, StorageClass_Storage_Struct) { TEST_F(ResolverAtomicValidationTest, AddressSpace_Storage_Struct) {
auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))}); auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))});
GlobalVar("g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kReadWrite, Group(0_a), GlobalVar("g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kReadWrite, Group(0_a),
Binding(0_a)); Binding(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverAtomicValidationTest, InvalidType) { TEST_F(ResolverAtomicValidationTest, InvalidType) {
GlobalVar("a", ty.atomic(ty.f32(Source{{12, 34}})), ast::StorageClass::kWorkgroup); GlobalVar("a", ty.atomic(ty.f32(Source{{12, 34}})), ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: atomic only supports i32 or u32 types"); EXPECT_EQ(r()->error(), "12:34 error: atomic only supports i32 or u32 types");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Simple) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Simple) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kPrivate); GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: atomic variables must have <storage> or <workgroup> " "12:34 error: atomic variables must have <storage> or <workgroup> "
"storage class"); "address space");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Array) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Array) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kPrivate); GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: atomic variables must have <storage> or <workgroup> " "12:34 error: atomic variables must have <storage> or <workgroup> "
"storage class"); "address space");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Struct) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Struct) {
auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))}); auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))});
GlobalVar("g", ty.Of(s), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(s), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"note: atomic sub-type of 's' is declared here"); "note: atomic sub-type of 's' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStruct) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_StructOfStruct) {
// struct Inner { m : atomic<i32>; }; // struct Inner { m : atomic<i32>; };
// struct Outer { m : array<Inner, 4>; }; // struct Outer { m : array<Inner, 4>; };
// var<private> g : Outer; // var<private> g : Outer;
@ -91,16 +91,16 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStruct) {
auto* Inner = auto* Inner =
Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))}); Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))});
auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))}); auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))});
GlobalVar("g", ty.Of(Outer), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(Outer), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"note: atomic sub-type of 'Outer' is declared here"); "note: atomic sub-type of 'Outer' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStructOfArray) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_StructOfStructOfArray) {
// struct Inner { m : array<atomic<i32>, 4>; }; // struct Inner { m : array<atomic<i32>, 4>; };
// struct Outer { m : array<Inner, 4>; }; // struct Outer { m : array<Inner, 4>; };
// var<private> g : Outer; // var<private> g : Outer;
@ -108,46 +108,46 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStructOfArray)
auto* Inner = auto* Inner =
Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))}); Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))});
auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))}); auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))});
GlobalVar("g", ty.Of(Outer), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(Outer), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"12:34 note: atomic sub-type of 'Outer' is declared here"); "12:34 note: atomic sub-type of 'Outer' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfArray) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfArray) {
// type AtomicArray = array<atomic<i32>, 5>; // type AtomicArray = array<atomic<i32>, 5>;
// var<private> v: array<s, 5>; // var<private> v: array<s, 5>;
auto* atomic_array = auto* atomic_array =
Alias(Source{{12, 34}}, "AtomicArray", ty.atomic(Source{{12, 34}}, ty.i32())); Alias(Source{{12, 34}}, "AtomicArray", ty.atomic(Source{{12, 34}}, ty.i32()));
GlobalVar(Source{{56, 78}}, "v", ty.Of(atomic_array), ast::StorageClass::kPrivate); GlobalVar(Source{{56, 78}}, "v", ty.Of(atomic_array), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class"); "address space");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStruct) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfStruct) {
// struct S{ // struct S{
// m: atomic<u32>; // m: atomic<u32>;
// }; // };
// var<private> v: array<S, 5u>; // var<private> v: array<S, 5u>;
auto* s = Structure("S", utils::Vector{Member("m", ty.atomic<u32>())}); auto* s = Structure("S", utils::Vector{Member("m", ty.atomic<u32>())});
GlobalVar(Source{{56, 78}}, "v", ty.array(ty.Of(s), 5_u), ast::StorageClass::kPrivate); GlobalVar(Source{{56, 78}}, "v", ty.array(ty.Of(s), 5_u), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"note: atomic sub-type of 'array<S, 5>' is declared here"); "note: atomic sub-type of 'array<S, 5>' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStructOfArray) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfStructOfArray) {
// type AtomicArray = array<atomic<i32>, 5u>; // type AtomicArray = array<atomic<i32>, 5u>;
// struct S{ // struct S{
// m: AtomicArray; // m: AtomicArray;
@ -157,16 +157,16 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStructOfArray) {
auto* atomic_array = auto* atomic_array =
Alias(Source{{12, 34}}, "AtomicArray", ty.atomic(Source{{12, 34}}, ty.i32())); Alias(Source{{12, 34}}, "AtomicArray", ty.atomic(Source{{12, 34}}, ty.i32()));
auto* s = Structure("S", utils::Vector{Member("m", ty.Of(atomic_array))}); auto* s = Structure("S", utils::Vector{Member("m", ty.Of(atomic_array))});
GlobalVar(Source{{56, 78}}, "v", ty.array(ty.Of(s), 5_u), ast::StorageClass::kPrivate); GlobalVar(Source{{56, 78}}, "v", ty.array(ty.Of(s), 5_u), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"note: atomic sub-type of 'array<S, 5>' is declared here"); "note: atomic sub-type of 'array<S, 5>' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Complex) { TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Complex) {
// type AtomicArray = array<atomic<i32>, 5u>; // type AtomicArray = array<atomic<i32>, 5u>;
// struct S6 { x: array<i32, 4>; }; // struct S6 { x: array<i32, 4>; };
// struct S5 { x: S6; // struct S5 { x: S6;
@ -198,35 +198,35 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Complex) {
auto* s2 = Structure("S2", utils::Vector{Member("x", ty.Of(s3))}); auto* s2 = Structure("S2", utils::Vector{Member("x", ty.Of(s3))});
auto* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))}); auto* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))});
auto* s0 = Structure("S0", utils::Vector{Member("x", ty.Of(s1))}); auto* s0 = Structure("S0", utils::Vector{Member("x", ty.Of(s1))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s0), ast::StorageClass::kPrivate); GlobalVar(Source{{56, 78}}, "g", ty.Of(s0), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> " "error: atomic variables must have <storage> or <workgroup> "
"storage class\n" "address space\n"
"note: atomic sub-type of 'S0' is declared here"); "note: atomic sub-type of 'S0' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, Struct_AccessMode_Read) { TEST_F(ResolverAtomicValidationTest, Struct_AccessMode_Read) {
auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))}); auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables in <storage> storage class must have read_write " "error: atomic variables in <storage> address space must have read_write "
"access mode\n" "access mode\n"
"note: atomic sub-type of 's' is declared here"); "note: atomic sub-type of 's' is declared here");
} }
TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_Struct) { TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_Struct) {
auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))}); auto* s = Structure("s", utils::Vector{Member("a", ty.atomic(Source{{12, 34}}, ty.i32()))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables in <storage> storage class must have read_write " "error: atomic variables in <storage> address space must have read_write "
"access mode\n" "access mode\n"
"note: atomic sub-type of 's' is declared here"); "note: atomic sub-type of 's' is declared here");
} }
@ -239,12 +239,12 @@ TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_StructOfStruct) {
auto* Inner = auto* Inner =
Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))}); Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))});
auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))}); auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(Outer), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(Outer), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables in <storage> storage class must have read_write " "error: atomic variables in <storage> address space must have read_write "
"access mode\n" "access mode\n"
"note: atomic sub-type of 'Outer' is declared here"); "note: atomic sub-type of 'Outer' is declared here");
} }
@ -257,12 +257,12 @@ TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_StructOfStructOfArray) {
auto* Inner = auto* Inner =
Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))}); Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))});
auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))}); auto* Outer = Structure("Outer", utils::Vector{Member("m", ty.Of(Inner))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(Outer), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(Outer), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables in <storage> storage class must have " "error: atomic variables in <storage> address space must have "
"read_write access mode\n" "read_write access mode\n"
"12:34 note: atomic sub-type of 'Outer' is declared here"); "12:34 note: atomic sub-type of 'Outer' is declared here");
} }
@ -299,12 +299,12 @@ TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_Complex) {
auto* s2 = Structure("S2", utils::Vector{Member("x", ty.Of(s3))}); auto* s2 = Structure("S2", utils::Vector{Member("x", ty.Of(s3))});
auto* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))}); auto* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))});
auto* s0 = Structure("S0", utils::Vector{Member("x", ty.Of(s1))}); auto* s0 = Structure("S0", utils::Vector{Member("x", ty.Of(s1))});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s0), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s0), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: atomic variables in <storage> storage class must have " "error: atomic variables in <storage> address space must have "
"read_write access mode\n" "read_write access mode\n"
"note: atomic sub-type of 'S0' is declared here"); "note: atomic sub-type of 'S0' is declared here");
} }

View File

@ -721,7 +721,7 @@ TEST_F(StructMemberAttributeTest, Align_Attribute_ConstAFloat) {
} }
TEST_F(StructMemberAttributeTest, Align_Attribute_Var) { TEST_F(StructMemberAttributeTest, Align_Attribute_Var) {
GlobalVar(Source{{1, 2}}, "val", ty.f32(), ast::StorageClass::kPrivate, ast::Access::kUndefined, GlobalVar(Source{{1, 2}}, "val", ty.f32(), ast::AddressSpace::kPrivate, ast::Access::kUndefined,
Expr(1.23_f)); Expr(1.23_f));
Structure(Source{{6, 4}}, "mystruct", Structure(Source{{6, 4}}, "mystruct",
@ -785,7 +785,7 @@ TEST_P(VariableAttributeTest, IsValid) {
if (IsBindingAttribute(params.kind)) { if (IsBindingAttribute(params.kind)) {
GlobalVar("a", ty.sampler(ast::SamplerKind::kSampler), attrs); GlobalVar("a", ty.sampler(ast::SamplerKind::kSampler), attrs);
} else { } else {
GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate, attrs); GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate, attrs);
} }
if (params.should_pass) { if (params.should_pass) {
@ -956,7 +956,7 @@ TEST_P(ArrayStrideTest, All) {
create<ast::StrideAttribute>(Source{{12, 34}}, params.stride), create<ast::StrideAttribute>(Source{{12, 34}}, params.stride),
}); });
GlobalVar("myarray", arr, ast::StorageClass::kPrivate); GlobalVar("myarray", arr, ast::AddressSpace::kPrivate);
if (params.should_pass) { if (params.should_pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -1039,7 +1039,7 @@ TEST_F(ArrayStrideTest, DuplicateAttribute) {
create<ast::StrideAttribute>(Source{{56, 78}}, 4u), create<ast::StrideAttribute>(Source{{56, 78}}, 4u),
}); });
GlobalVar("myarray", arr, ast::StorageClass::kPrivate); GlobalVar("myarray", arr, ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -1058,7 +1058,7 @@ TEST_F(ResourceAttributeTest, UniformBufferMissingBinding) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("x", ty.i32()), Member("x", ty.i32()),
}); });
GlobalVar(Source{{12, 34}}, "G", ty.Of(s), ast::StorageClass::kUniform); GlobalVar(Source{{12, 34}}, "G", ty.Of(s), ast::AddressSpace::kUniform);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -1069,7 +1069,7 @@ TEST_F(ResourceAttributeTest, StorageBufferMissingBinding) {
auto* s = Structure("S", utils::Vector{ auto* s = Structure("S", utils::Vector{
Member("x", ty.i32()), Member("x", ty.i32()),
}); });
GlobalVar(Source{{12, 34}}, "G", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead); GlobalVar(Source{{12, 34}}, "G", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -1155,7 +1155,7 @@ TEST_F(ResourceAttributeTest, BindingPointUsedTwiceByDifferentEntryPoints) {
} }
TEST_F(ResourceAttributeTest, BindingPointOnNonResource) { TEST_F(ResourceAttributeTest, BindingPointOnNonResource) {
GlobalVar(Source{{12, 34}}, "G", ty.f32(), ast::StorageClass::kPrivate, Binding(1_a), GlobalVar(Source{{12, 34}}, "G", ty.f32(), ast::AddressSpace::kPrivate, Binding(1_a),
Group(2_a)); Group(2_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -78,7 +78,7 @@ using ResolverBuiltinTest_BoolMethod = ResolverTestWithParam<std::string>;
TEST_P(ResolverBuiltinTest_BoolMethod, Scalar) { TEST_P(ResolverBuiltinTest_BoolMethod, Scalar) {
auto name = GetParam(); auto name = GetParam();
GlobalVar("my_var", ty.bool_(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.bool_(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "my_var"); auto* expr = Call(name, "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -91,7 +91,7 @@ TEST_P(ResolverBuiltinTest_BoolMethod, Scalar) {
TEST_P(ResolverBuiltinTest_BoolMethod, Vector) { TEST_P(ResolverBuiltinTest_BoolMethod, Vector) {
auto name = GetParam(); auto name = GetParam();
GlobalVar("my_var", ty.vec3<bool>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<bool>(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "my_var"); auto* expr = Call(name, "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -106,9 +106,9 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
testing::Values("any", "all")); testing::Values("any", "all"));
TEST_F(ResolverBuiltinTest, Select) { TEST_F(ResolverBuiltinTest, Select) {
GlobalVar("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
GlobalVar("bool_var", ty.vec3<bool>(), ast::StorageClass::kPrivate); GlobalVar("bool_var", ty.vec3<bool>(), ast::AddressSpace::kPrivate);
auto* expr = Call("select", "my_var", "my_var", "bool_var"); auto* expr = Call("select", "my_var", "my_var", "bool_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -212,7 +212,7 @@ using ResolverBuiltinArrayTest = ResolverTest;
TEST_F(ResolverBuiltinArrayTest, ArrayLength_Vector) { TEST_F(ResolverBuiltinArrayTest, ArrayLength_Vector) {
auto* ary = ty.array<i32>(); auto* ary = ty.array<i32>();
auto* str = Structure("S", utils::Vector{Member("x", ary)}); auto* str = Structure("S", utils::Vector{Member("x", ary)});
GlobalVar("a", ty.Of(str), ast::StorageClass::kStorage, ast::Access::kRead, Binding(0_a), GlobalVar("a", ty.Of(str), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
Group(0_a)); Group(0_a));
auto* call = Call("arrayLength", AddressOf(MemberAccessor("a", "x"))); auto* call = Call("arrayLength", AddressOf(MemberAccessor("a", "x")));
@ -225,7 +225,7 @@ TEST_F(ResolverBuiltinArrayTest, ArrayLength_Vector) {
} }
TEST_F(ResolverBuiltinArrayTest, ArrayLength_Error_ArraySized) { TEST_F(ResolverBuiltinArrayTest, ArrayLength_Error_ArraySized) {
GlobalVar("arr", ty.array<i32, 4>(), ast::StorageClass::kPrivate); GlobalVar("arr", ty.array<i32, 4>(), ast::AddressSpace::kPrivate);
auto* call = Call("arrayLength", AddressOf("arr")); auto* call = Call("arrayLength", AddressOf("arr"));
WrapInFunction(call); WrapInFunction(call);
@ -1029,7 +1029,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpVector_f16) {
} }
TEST_F(ResolverBuiltinFloatTest, Frexp_Error_FirstParamInt) { TEST_F(ResolverBuiltinFloatTest, Frexp_Error_FirstParamInt) {
GlobalVar("v", ty.i32(), ast::StorageClass::kWorkgroup); GlobalVar("v", ty.i32(), ast::AddressSpace::kWorkgroup);
auto* call = Call("frexp", 1_i, AddressOf("v")); auto* call = Call("frexp", 1_i, AddressOf("v"));
WrapInFunction(call); WrapInFunction(call);
@ -1045,7 +1045,7 @@ TEST_F(ResolverBuiltinFloatTest, Frexp_Error_FirstParamInt) {
} }
TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamFloatPtr) { TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamFloatPtr) {
GlobalVar("v", ty.f32(), ast::StorageClass::kWorkgroup); GlobalVar("v", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* call = Call("frexp", 1_f, AddressOf("v")); auto* call = Call("frexp", 1_f, AddressOf("v"));
WrapInFunction(call); WrapInFunction(call);
@ -1075,7 +1075,7 @@ TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamNotAPointer) {
} }
TEST_F(ResolverBuiltinFloatTest, Frexp_Error_VectorSizesDontMatch) { TEST_F(ResolverBuiltinFloatTest, Frexp_Error_VectorSizesDontMatch) {
GlobalVar("v", ty.vec4<i32>(), ast::StorageClass::kWorkgroup); GlobalVar("v", ty.vec4<i32>(), ast::AddressSpace::kWorkgroup);
auto* call = Call("frexp", vec2<f32>(1_f, 2_f), AddressOf("v")); auto* call = Call("frexp", vec2<f32>(1_f, 2_f), AddressOf("v"));
WrapInFunction(call); WrapInFunction(call);
@ -1324,7 +1324,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfVector_f16) {
} }
TEST_F(ResolverBuiltinFloatTest, Modf_Error_FirstParamInt) { TEST_F(ResolverBuiltinFloatTest, Modf_Error_FirstParamInt) {
GlobalVar("whole", ty.f32(), ast::StorageClass::kWorkgroup); GlobalVar("whole", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* call = Call("modf", 1_i, AddressOf("whole")); auto* call = Call("modf", 1_i, AddressOf("whole"));
WrapInFunction(call); WrapInFunction(call);
@ -1340,7 +1340,7 @@ TEST_F(ResolverBuiltinFloatTest, Modf_Error_FirstParamInt) {
} }
TEST_F(ResolverBuiltinFloatTest, Modf_Error_SecondParamIntPtr) { TEST_F(ResolverBuiltinFloatTest, Modf_Error_SecondParamIntPtr) {
GlobalVar("whole", ty.i32(), ast::StorageClass::kWorkgroup); GlobalVar("whole", ty.i32(), ast::AddressSpace::kWorkgroup);
auto* call = Call("modf", 1_f, AddressOf("whole")); auto* call = Call("modf", 1_f, AddressOf("whole"));
WrapInFunction(call); WrapInFunction(call);
@ -1370,7 +1370,7 @@ TEST_F(ResolverBuiltinFloatTest, Modf_Error_SecondParamNotAPointer) {
} }
TEST_F(ResolverBuiltinFloatTest, Modf_Error_VectorSizesDontMatch) { TEST_F(ResolverBuiltinFloatTest, Modf_Error_VectorSizesDontMatch) {
GlobalVar("whole", ty.vec4<f32>(), ast::StorageClass::kWorkgroup); GlobalVar("whole", ty.vec4<f32>(), ast::AddressSpace::kWorkgroup);
auto* call = Call("modf", vec2<f32>(1_f, 2_f), AddressOf("whole")); auto* call = Call("modf", vec2<f32>(1_f, 2_f), AddressOf("whole"));
WrapInFunction(call); WrapInFunction(call);
@ -1850,7 +1850,7 @@ INSTANTIATE_TEST_SUITE_P(
namespace matrix_builtin_tests { namespace matrix_builtin_tests {
TEST_F(ResolverBuiltinTest, Determinant_2x2_f32) { TEST_F(ResolverBuiltinTest, Determinant_2x2_f32) {
GlobalVar("var", ty.mat2x2<f32>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat2x2<f32>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1864,7 +1864,7 @@ TEST_F(ResolverBuiltinTest, Determinant_2x2_f32) {
TEST_F(ResolverBuiltinTest, Determinant_2x2_f16) { TEST_F(ResolverBuiltinTest, Determinant_2x2_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("var", ty.mat2x2<f16>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat2x2<f16>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1876,7 +1876,7 @@ TEST_F(ResolverBuiltinTest, Determinant_2x2_f16) {
} }
TEST_F(ResolverBuiltinTest, Determinant_3x3_f32) { TEST_F(ResolverBuiltinTest, Determinant_3x3_f32) {
GlobalVar("var", ty.mat3x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat3x3<f32>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1890,7 +1890,7 @@ TEST_F(ResolverBuiltinTest, Determinant_3x3_f32) {
TEST_F(ResolverBuiltinTest, Determinant_3x3_f16) { TEST_F(ResolverBuiltinTest, Determinant_3x3_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("var", ty.mat3x3<f16>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat3x3<f16>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1902,7 +1902,7 @@ TEST_F(ResolverBuiltinTest, Determinant_3x3_f16) {
} }
TEST_F(ResolverBuiltinTest, Determinant_4x4_f32) { TEST_F(ResolverBuiltinTest, Determinant_4x4_f32) {
GlobalVar("var", ty.mat4x4<f32>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat4x4<f32>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1916,7 +1916,7 @@ TEST_F(ResolverBuiltinTest, Determinant_4x4_f32) {
TEST_F(ResolverBuiltinTest, Determinant_4x4_f16) { TEST_F(ResolverBuiltinTest, Determinant_4x4_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("var", ty.mat4x4<f16>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat4x4<f16>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1928,7 +1928,7 @@ TEST_F(ResolverBuiltinTest, Determinant_4x4_f16) {
} }
TEST_F(ResolverBuiltinTest, Determinant_NotSquare) { TEST_F(ResolverBuiltinTest, Determinant_NotSquare) {
GlobalVar("var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("var", ty.mat2x3<f32>(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1943,7 +1943,7 @@ TEST_F(ResolverBuiltinTest, Determinant_NotSquare) {
} }
TEST_F(ResolverBuiltinTest, Determinant_NotMatrix) { TEST_F(ResolverBuiltinTest, Determinant_NotMatrix) {
GlobalVar("var", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("var", ty.f32(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var"); auto* call = Call("determinant", "var");
WrapInFunction(call); WrapInFunction(call);
@ -1963,7 +1963,7 @@ TEST_F(ResolverBuiltinTest, Determinant_NotMatrix) {
namespace vector_builtin_tests { namespace vector_builtin_tests {
TEST_F(ResolverBuiltinTest, Dot_Vec2_f32) { TEST_F(ResolverBuiltinTest, Dot_Vec2_f32) {
GlobalVar("my_var", ty.vec2<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec2<f32>(), ast::AddressSpace::kPrivate);
auto* expr = Call("dot", "my_var", "my_var"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -1977,7 +1977,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec2_f32) {
TEST_F(ResolverBuiltinTest, Dot_Vec2_f16) { TEST_F(ResolverBuiltinTest, Dot_Vec2_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("my_var", ty.vec2<f16>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec2<f16>(), ast::AddressSpace::kPrivate);
auto* expr = Call("dot", "my_var", "my_var"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -1989,7 +1989,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec2_f16) {
} }
TEST_F(ResolverBuiltinTest, Dot_Vec3_i32) { TEST_F(ResolverBuiltinTest, Dot_Vec3_i32) {
GlobalVar("my_var", ty.vec3<i32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec3<i32>(), ast::AddressSpace::kPrivate);
auto* expr = Call("dot", "my_var", "my_var"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -2001,7 +2001,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec3_i32) {
} }
TEST_F(ResolverBuiltinTest, Dot_Vec4_u32) { TEST_F(ResolverBuiltinTest, Dot_Vec4_u32) {
GlobalVar("my_var", ty.vec4<u32>(), ast::StorageClass::kPrivate); GlobalVar("my_var", ty.vec4<u32>(), ast::AddressSpace::kPrivate);
auto* expr = Call("dot", "my_var", "my_var"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -2036,7 +2036,7 @@ using ResolverBuiltinDerivativeTest = ResolverTestWithParam<std::string>;
TEST_P(ResolverBuiltinDerivativeTest, Scalar) { TEST_P(ResolverBuiltinDerivativeTest, Scalar) {
auto name = GetParam(); auto name = GetParam();
GlobalVar("ident", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.f32(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "ident"); auto* expr = Call(name, "ident");
Func("func", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)}, Func("func", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)},
@ -2050,7 +2050,7 @@ TEST_P(ResolverBuiltinDerivativeTest, Scalar) {
TEST_P(ResolverBuiltinDerivativeTest, Vector) { TEST_P(ResolverBuiltinDerivativeTest, Vector) {
auto name = GetParam(); auto name = GetParam();
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "ident"); auto* expr = Call(name, "ident");
Func("func", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)}, Func("func", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)},
@ -2146,7 +2146,7 @@ class ResolverBuiltinTest_TextureOperation : public ResolverTestWithParam<Textur
GlobalVar(name, type, Binding(0_a), Group(0_a)); GlobalVar(name, type, Binding(0_a), Group(0_a));
} else { } else {
GlobalVar(name, type, ast::StorageClass::kPrivate); GlobalVar(name, type, ast::AddressSpace::kPrivate);
} }
call_params->Push(Expr(name)); call_params->Push(Expr(name));

View File

@ -113,7 +113,7 @@ TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalConst) {
} }
TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalVar) { TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalVar) {
GlobalVar(Source{{12, 34}}, "mix", ty.i32(), Expr(1_i), ast::StorageClass::kPrivate); GlobalVar(Source{{12, 34}}, "mix", ty.i32(), Expr(1_i), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(

View File

@ -100,7 +100,7 @@ using ResolverBuiltinsStageTest = ResolverTestWithParam<Params>;
TEST_P(ResolverBuiltinsStageTest, All_input) { TEST_P(ResolverBuiltinsStageTest, All_input) {
const Params& params = GetParam(); const Params& params = GetParam();
auto* p = GlobalVar("p", ty.vec4<f32>(), ast::StorageClass::kPrivate); auto* p = GlobalVar("p", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* input = Param("input", params.type(*this), auto* input = Param("input", params.type(*this),
utils::Vector{Builtin(Source{{12, 34}}, params.builtin)}); utils::Vector{Builtin(Source{{12, 34}}, params.builtin)});
switch (params.stage) { switch (params.stage) {

View File

@ -103,7 +103,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_VariableIdentExpr) {
// var z: i32 = 1i; // var z: i32 = 1i;
// foo(&z); // foo(&z);
// } // }
auto* param = Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)); auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty); Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -120,7 +120,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_ConstIdentExpr) {
// let z: i32 = 1i; // let z: i32 = 1i;
// foo(&z); // foo(&z);
// } // }
auto* param = Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)); auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty); Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -142,7 +142,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_NotIdentExprVar) {
auto* S = Structure("S", utils::Vector{ auto* S = Structure("S", utils::Vector{
Member("m", ty.i32()), Member("m", ty.i32()),
}); });
auto* param = Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)); auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty); Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -166,7 +166,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_AddressOfMemberAccessor) {
auto* S = Structure("S", utils::Vector{ auto* S = Structure("S", utils::Vector{
Member("m", ty.i32()), Member("m", ty.i32()),
}); });
auto* param = Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)); auto* param = Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction));
Func("foo", utils::Vector{param}, ty.void_(), utils::Empty); Func("foo", utils::Vector{param}, ty.void_(), utils::Empty);
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -185,12 +185,12 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParam) {
// } // }
Func("foo", Func("foo",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)), Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
}, },
ty.void_(), utils::Empty); ty.void_(), utils::Empty);
Func("bar", Func("bar",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)), Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
}, },
ty.void_(), ty.void_(),
utils::Vector{ utils::Vector{
@ -212,12 +212,12 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
// } // }
Func("foo", Func("foo",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)), Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
}, },
ty.void_(), utils::Empty); ty.void_(), utils::Empty);
Func("bar", Func("bar",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)), Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
}, },
ty.void_(), ty.void_(),
utils::Vector{ utils::Vector{
@ -245,11 +245,11 @@ TEST_F(ResolverCallValidationTest, LetPointer) {
// } // }
Func("x", Func("x",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kFunction)), Param("p", ty.pointer<i32>(ast::AddressSpace::kFunction)),
}, },
ty.void_(), utils::Empty); ty.void_(), utils::Empty);
auto* v = Var("v", ty.i32()); auto* v = Var("v", ty.i32());
auto* p = Let("p", ty.pointer(ty.i32(), ast::StorageClass::kFunction), AddressOf(v)); auto* p = Let("p", ty.pointer(ty.i32(), ast::AddressSpace::kFunction), AddressOf(v));
auto* c = Var("c", ty.i32(), Call("x", Expr(Source{{12, 34}}, p))); auto* c = Var("c", ty.i32(), Call("x", Expr(Source{{12, 34}}, p)));
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -276,11 +276,11 @@ TEST_F(ResolverCallValidationTest, LetPointerPrivate) {
// } // }
Func("foo", Func("foo",
utils::Vector{ utils::Vector{
Param("p", ty.pointer<i32>(ast::StorageClass::kPrivate)), Param("p", ty.pointer<i32>(ast::AddressSpace::kPrivate)),
}, },
ty.void_(), utils::Empty); ty.void_(), utils::Empty);
auto* v = GlobalVar("v", ty.i32(), ast::StorageClass::kPrivate); auto* v = GlobalVar("v", ty.i32(), ast::AddressSpace::kPrivate);
auto* p = Let("p", ty.pointer(ty.i32(), ast::StorageClass::kPrivate), AddressOf(v)); auto* p = Let("p", ty.pointer(ty.i32(), ast::AddressSpace::kPrivate), AddressOf(v));
auto* c = Var("c", ty.i32(), Call("foo", Expr(Source{{12, 34}}, p))); auto* c = Var("c", ty.i32(), Call("foo", Expr(Source{{12, 34}}, p)));
Func("main", utils::Empty, ty.void_(), Func("main", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -301,7 +301,7 @@ TEST_F(ResolverCallValidationTest, CallVariable) {
// fn f() { // fn f() {
// v(); // v();
// } // }
GlobalVar("v", ty.i32(), ast::StorageClass::kPrivate); GlobalVar("v", ty.i32(), ast::AddressSpace::kPrivate);
Func("f", utils::Empty, ty.void_(), Func("f", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
CallStmt(Call(Source{{12, 34}}, "v")), CallStmt(Call(Source{{12, 34}}, "v")),

View File

@ -51,7 +51,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, CompatibleTypesAssignThroughPoi
// var a : i32; // var a : i32;
// let b : ptr<function,i32> = &a; // let b : ptr<function,i32> = &a;
// *b += 2; // *b += 2;
const auto func = ast::StorageClass::kFunction; const auto func = ast::AddressSpace::kFunction;
auto* var_a = Var("a", ty.i32(), func, Expr(2_i)); auto* var_a = Var("a", ty.i32(), func, Expr(2_i));
auto* var_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("a"))); auto* var_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b, WrapInFunction(var_a, var_b,
@ -233,7 +233,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, ReadOnlyBuffer) {
// { // {
// a += 1i; // a += 1i;
// } // }
GlobalVar(Source{{12, 34}}, "a", ty.i32(), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{12, 34}}, "a", ty.i32(), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
WrapInFunction(CompoundAssign(Source{{56, 78}}, "a", 1_i, ast::BinaryOp::kAdd)); WrapInFunction(CompoundAssign(Source{{56, 78}}, "a", 1_i, ast::BinaryOp::kAdd));
@ -264,7 +264,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, LhsLiteral) {
TEST_F(ResolverCompoundAssignmentValidationTest, LhsAtomic) { TEST_F(ResolverCompoundAssignmentValidationTest, LhsAtomic) {
// var<workgroup> a : atomic<i32>; // var<workgroup> a : atomic<i32>;
// a += a; // a += a;
GlobalVar(Source{{12, 34}}, "a", ty.atomic(ty.i32()), ast::StorageClass::kWorkgroup); GlobalVar(Source{{12, 34}}, "a", ty.atomic(ty.i32()), ast::AddressSpace::kWorkgroup);
WrapInFunction(CompoundAssign(Source{{56, 78}}, "a", "a", ast::BinaryOp::kAdd)); WrapInFunction(CompoundAssign(Source{{56, 78}}, "a", "a", ast::BinaryOp::kAdd));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -2666,7 +2666,7 @@ TEST_F(ResolverConstEvalTest, Array_vec3_f32_Index_OOB_Low) {
TEST_F(ResolverConstEvalTest, RuntimeArray_vec3_f32_Index_OOB_Low) { TEST_F(ResolverConstEvalTest, RuntimeArray_vec3_f32_Index_OOB_Low) {
auto* sb = GlobalVar("sb", ty.array(ty.vec3<f32>()), Group(0_a), Binding(0_a), auto* sb = GlobalVar("sb", ty.array(ty.vec3<f32>()), Group(0_a), Binding(0_a),
ast::StorageClass::kStorage); ast::AddressSpace::kStorage);
auto* expr = IndexAccessor(sb, Expr(Source{{12, 34}}, -2_i)); auto* expr = IndexAccessor(sb, Expr(Source{{12, 34}}, -2_i));
WrapInFunction(expr); WrapInFunction(expr);

View File

@ -425,7 +425,7 @@ const ast::Node* SymbolTestHelper::Add(SymbolDeclKind kind, Symbol symbol, Sourc
auto& b = *builder; auto& b = *builder;
switch (kind) { switch (kind) {
case SymbolDeclKind::GlobalVar: case SymbolDeclKind::GlobalVar:
return b.GlobalVar(source, symbol, b.ty.i32(), ast::StorageClass::kPrivate); return b.GlobalVar(source, symbol, b.ty.i32(), ast::AddressSpace::kPrivate);
case SymbolDeclKind::GlobalConst: case SymbolDeclKind::GlobalConst:
return b.GlobalConst(source, symbol, b.ty.i32(), b.Expr(1_i)); return b.GlobalConst(source, symbol, b.ty.i32(), b.Expr(1_i));
case SymbolDeclKind::Alias: case SymbolDeclKind::Alias:
@ -468,27 +468,27 @@ const ast::Node* SymbolTestHelper::Add(SymbolUseKind kind, Symbol symbol, Source
switch (kind) { switch (kind) {
case SymbolUseKind::GlobalVarType: { case SymbolUseKind::GlobalVarType: {
auto* node = b.ty.type_name(source, symbol); auto* node = b.ty.type_name(source, symbol);
b.GlobalVar(b.Sym(), node, ast::StorageClass::kPrivate); b.GlobalVar(b.Sym(), node, ast::AddressSpace::kPrivate);
return node; return node;
} }
case SymbolUseKind::GlobalVarArrayElemType: { case SymbolUseKind::GlobalVarArrayElemType: {
auto* node = b.ty.type_name(source, symbol); auto* node = b.ty.type_name(source, symbol);
b.GlobalVar(b.Sym(), b.ty.array(node, 4_i), ast::StorageClass::kPrivate); b.GlobalVar(b.Sym(), b.ty.array(node, 4_i), ast::AddressSpace::kPrivate);
return node; return node;
} }
case SymbolUseKind::GlobalVarArraySizeValue: { case SymbolUseKind::GlobalVarArraySizeValue: {
auto* node = b.Expr(source, symbol); auto* node = b.Expr(source, symbol);
b.GlobalVar(b.Sym(), b.ty.array(b.ty.i32(), node), ast::StorageClass::kPrivate); b.GlobalVar(b.Sym(), b.ty.array(b.ty.i32(), node), ast::AddressSpace::kPrivate);
return node; return node;
} }
case SymbolUseKind::GlobalVarVectorElemType: { case SymbolUseKind::GlobalVarVectorElemType: {
auto* node = b.ty.type_name(source, symbol); auto* node = b.ty.type_name(source, symbol);
b.GlobalVar(b.Sym(), b.ty.vec3(node), ast::StorageClass::kPrivate); b.GlobalVar(b.Sym(), b.ty.vec3(node), ast::AddressSpace::kPrivate);
return node; return node;
} }
case SymbolUseKind::GlobalVarMatrixElemType: { case SymbolUseKind::GlobalVarMatrixElemType: {
auto* node = b.ty.type_name(source, symbol); auto* node = b.ty.type_name(source, symbol);
b.GlobalVar(b.Sym(), b.ty.mat3x4(node), ast::StorageClass::kPrivate); b.GlobalVar(b.Sym(), b.ty.mat3x4(node), ast::AddressSpace::kPrivate);
return node; return node;
} }
case SymbolUseKind::GlobalVarSampledTexElemType: { case SymbolUseKind::GlobalVarSampledTexElemType: {
@ -503,7 +503,7 @@ const ast::Node* SymbolTestHelper::Add(SymbolUseKind kind, Symbol symbol, Source
} }
case SymbolUseKind::GlobalVarValue: { case SymbolUseKind::GlobalVarValue: {
auto* node = b.Expr(source, symbol); auto* node = b.Expr(source, symbol);
b.GlobalVar(b.Sym(), b.ty.i32(), ast::StorageClass::kPrivate, node); b.GlobalVar(b.Sym(), b.ty.i32(), ast::AddressSpace::kPrivate, node);
return node; return node;
} }
case SymbolUseKind::GlobalConstType: { case SymbolUseKind::GlobalConstType: {
@ -724,7 +724,7 @@ TEST_F(ResolverDependencyGraphUsedBeforeDeclTest, VarUsed) {
Block(Assign(Expr(Source{{12, 34}}, "G"), 3.14_f)), Block(Assign(Expr(Source{{12, 34}}, "G"), 3.14_f)),
}); });
GlobalVar(Source{{56, 78}}, "G", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1_f)); GlobalVar(Source{{56, 78}}, "G", ty.f32(), ast::AddressSpace::kPrivate, Expr(2.1_f));
Build(); Build();
} }
@ -1207,7 +1207,7 @@ TEST_F(ResolverDependencyGraphTraversalTest, SymbolsReached) {
const auto type_sym = Sym("TYPE"); const auto type_sym = Sym("TYPE");
const auto func_sym = Sym("FUNC"); const auto func_sym = Sym("FUNC");
const auto* value_decl = GlobalVar(value_sym, ty.i32(), ast::StorageClass::kPrivate); const auto* value_decl = GlobalVar(value_sym, ty.i32(), ast::AddressSpace::kPrivate);
const auto* type_decl = Alias(type_sym, ty.i32()); const auto* type_decl = Alias(type_sym, ty.i32());
const auto* func_decl = Func(func_sym, utils::Empty, ty.void_(), utils::Empty); const auto* func_decl = Func(func_sym, utils::Empty, ty.void_(), utils::Empty);
@ -1278,7 +1278,7 @@ TEST_F(ResolverDependencyGraphTraversalTest, SymbolsReached) {
GlobalVar(Sym(), ty.array(T, V, 4)); GlobalVar(Sym(), ty.array(T, V, 4));
GlobalVar(Sym(), ty.vec3(T)); GlobalVar(Sym(), ty.vec3(T));
GlobalVar(Sym(), ty.mat3x2(T)); GlobalVar(Sym(), ty.mat3x2(T));
GlobalVar(Sym(), ty.pointer(T, ast::StorageClass::kPrivate)); GlobalVar(Sym(), ty.pointer(T, ast::AddressSpace::kPrivate));
GlobalVar(Sym(), ty.sampled_texture(ast::TextureDimension::k2d, T)); GlobalVar(Sym(), ty.sampled_texture(ast::TextureDimension::k2d, T));
GlobalVar(Sym(), ty.depth_texture(ast::TextureDimension::k2d)); GlobalVar(Sym(), ty.depth_texture(ast::TextureDimension::k2d));
GlobalVar(Sym(), ty.depth_multisampled_texture(ast::TextureDimension::k2d)); GlobalVar(Sym(), ty.depth_multisampled_texture(ast::TextureDimension::k2d));

View File

@ -453,25 +453,25 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithEnable) {
// enable chromium_experimental_push_constant; // enable chromium_experimental_push_constant;
// var<push_constant> a : u32; // var<push_constant> a : u32;
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant);
EXPECT_TRUE(r()->Resolve()); EXPECT_TRUE(r()->Resolve());
} }
TEST_F(ResolverEntryPointValidationTest, PushConstantDisallowedWithoutEnable) { TEST_F(ResolverEntryPointValidationTest, PushConstantDisallowedWithoutEnable) {
// var<push_constant> a : u32; // var<push_constant> a : u32;
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::AddressSpace::kPushConstant);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"1:2 error: use of variable storage class 'push_constant' requires enabling " "1:2 error: use of variable address space 'push_constant' requires enabling "
"extension 'chromium_experimental_push_constant'"); "extension 'chromium_experimental_push_constant'");
} }
TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithIgnoreStorageClassAttribute) { TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithIgnoreAddressSpaceAttribute) {
// var<push_constant> a : u32; // With ast::DisabledValidation::kIgnoreStorageClass // var<push_constant> a : u32; // With ast::DisabledValidation::kIgnoreAddressSpace
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant, GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant,
utils::Vector{Disable(ast::DisabledValidation::kIgnoreStorageClass)}); utils::Vector{Disable(ast::DisabledValidation::kIgnoreAddressSpace)});
EXPECT_TRUE(r()->Resolve()); EXPECT_TRUE(r()->Resolve());
} }
@ -483,7 +483,7 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantOneVariableUsedInEntryPoint
// _ = a; // _ = a;
// } // }
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant);
Func("main", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")}, Func("main", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")},
utils::Vector{Stage(ast::PipelineStage::kCompute), utils::Vector{Stage(ast::PipelineStage::kCompute),
@ -501,8 +501,8 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInEntryPoin
// _ = b; // _ = b;
// } // }
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::AddressSpace::kPushConstant);
GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::AddressSpace::kPushConstant);
Func(Source{{5, 6}}, "main", {}, ty.void_(), Func(Source{{5, 6}}, "main", {}, ty.void_(),
utils::Vector{Assign(Phony(), "a"), Assign(Phony(), "b")}, utils::Vector{Assign(Phony(), "a"), Assign(Phony(), "b")},
@ -532,8 +532,8 @@ TEST_F(ResolverEntryPointValidationTest,
// uses_b(); // uses_b();
// } // }
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::AddressSpace::kPushConstant);
GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::AddressSpace::kPushConstant);
Func(Source{{5, 6}}, "uses_a", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")}); Func(Source{{5, 6}}, "uses_a", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")});
Func(Source{{7, 8}}, "uses_b", {}, ty.void_(), utils::Vector{Assign(Phony(), "b")}); Func(Source{{7, 8}}, "uses_b", {}, ty.void_(), utils::Vector{Assign(Phony(), "b")});
@ -565,8 +565,8 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInDifferent
// _ = a; // _ = a;
// } // }
Enable(ast::Extension::kChromiumExperimentalPushConstant); Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant);
GlobalVar("b", ty.u32(), ast::StorageClass::kPushConstant); GlobalVar("b", ty.u32(), ast::AddressSpace::kPushConstant);
Func("uses_a", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")}, Func("uses_a", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")},
utils::Vector{Stage(ast::PipelineStage::kCompute), utils::Vector{Stage(ast::PipelineStage::kCompute),

View File

@ -39,7 +39,7 @@ TEST_F(ResolverFunctionValidationTest, DuplicateParameterName) {
TEST_F(ResolverFunctionValidationTest, ParameterMayShadowGlobal) { TEST_F(ResolverFunctionValidationTest, ParameterMayShadowGlobal) {
// var<private> common_name : f32; // var<private> common_name : f32;
// fn func(common_name : f32) { } // fn func(common_name : f32) { }
GlobalVar("common_name", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("common_name", ty.f32(), ast::AddressSpace::kPrivate);
Func("func", utils::Vector{Param("common_name", ty.f32())}, ty.void_(), utils::Empty); Func("func", utils::Vector{Param("common_name", ty.f32())}, ty.void_(), utils::Empty);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -388,7 +388,7 @@ TEST_F(ResolverFunctionValidationTest, CannotCallFunctionAtModuleScope) {
utils::Vector{ utils::Vector{
Return(1_i), Return(1_i),
}); });
GlobalVar("x", Call(Source{{12, 34}}, "F"), ast::StorageClass::kPrivate); GlobalVar("x", Call(Source{{12, 34}}, "F"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: functions cannot be called at module-scope)"); EXPECT_EQ(r()->error(), R"(12:34 error: functions cannot be called at module-scope)");
@ -771,7 +771,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_NonConst) {
// var<private> x = 64i; // var<private> x = 64i;
// @compute @workgroup_size(x) // @compute @workgroup_size(x)
// fn main() {} // fn main() {}
GlobalVar("x", ty.i32(), ast::StorageClass::kPrivate, Expr(64_i)); GlobalVar("x", ty.i32(), ast::AddressSpace::kPrivate, Expr(64_i));
Func("main", utils::Empty, ty.void_(), utils::Empty, Func("main", utils::Empty, ty.void_(), utils::Empty,
utils::Vector{ utils::Vector{
Stage(ast::PipelineStage::kCompute), Stage(ast::PipelineStage::kCompute),
@ -830,7 +830,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_InvalidExpr_z) {
} }
TEST_F(ResolverFunctionValidationTest, ReturnIsConstructible_NonPlain) { TEST_F(ResolverFunctionValidationTest, ReturnIsConstructible_NonPlain) {
auto* ret_type = ty.pointer(Source{{12, 34}}, ty.i32(), ast::StorageClass::kFunction); auto* ret_type = ty.pointer(Source{{12, 34}}, ty.i32(), ast::AddressSpace::kFunction);
Func("f", utils::Empty, ret_type, utils::Empty); Func("f", utils::Empty, ret_type, utils::Empty);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -939,16 +939,16 @@ TEST_F(ResolverFunctionValidationTest, ParameterMatrixNoType) {
} }
struct TestParams { struct TestParams {
ast::StorageClass storage_class; ast::AddressSpace address_space;
bool should_pass; bool should_pass;
}; };
struct TestWithParams : ResolverTestWithParam<TestParams> {}; struct TestWithParams : ResolverTestWithParam<TestParams> {};
using ResolverFunctionParameterValidationTest = TestWithParams; using ResolverFunctionParameterValidationTest = TestWithParams;
TEST_P(ResolverFunctionParameterValidationTest, StorageClass) { TEST_P(ResolverFunctionParameterValidationTest, AddressSpace) {
auto& param = GetParam(); auto& param = GetParam();
auto* ptr_type = ty.pointer(Source{{12, 34}}, ty.i32(), param.storage_class); auto* ptr_type = ty.pointer(Source{{12, 34}}, ty.i32(), param.address_space);
auto* arg = Param(Source{{12, 34}}, "p", ptr_type); auto* arg = Param(Source{{12, 34}}, "p", ptr_type);
Func("f", utils::Vector{arg}, ty.void_(), utils::Empty); Func("f", utils::Vector{arg}, ty.void_(), utils::Empty);
@ -956,23 +956,23 @@ TEST_P(ResolverFunctionParameterValidationTest, StorageClass) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} else { } else {
std::stringstream ss; std::stringstream ss;
ss << param.storage_class; ss << param.address_space;
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: function parameter of pointer type cannot be in '" + EXPECT_EQ(r()->error(), "12:34 error: function parameter of pointer type cannot be in '" +
ss.str() + "' storage class"); ss.str() + "' address space");
} }
} }
INSTANTIATE_TEST_SUITE_P(ResolverTest, INSTANTIATE_TEST_SUITE_P(ResolverTest,
ResolverFunctionParameterValidationTest, ResolverFunctionParameterValidationTest,
testing::Values(TestParams{ast::StorageClass::kNone, false}, testing::Values(TestParams{ast::AddressSpace::kNone, false},
TestParams{ast::StorageClass::kIn, false}, TestParams{ast::AddressSpace::kIn, false},
TestParams{ast::StorageClass::kOut, false}, TestParams{ast::AddressSpace::kOut, false},
TestParams{ast::StorageClass::kUniform, false}, TestParams{ast::AddressSpace::kUniform, false},
TestParams{ast::StorageClass::kWorkgroup, true}, TestParams{ast::AddressSpace::kWorkgroup, true},
TestParams{ast::StorageClass::kHandle, false}, TestParams{ast::AddressSpace::kHandle, false},
TestParams{ast::StorageClass::kStorage, false}, TestParams{ast::AddressSpace::kStorage, false},
TestParams{ast::StorageClass::kPrivate, true}, TestParams{ast::AddressSpace::kPrivate, true},
TestParams{ast::StorageClass::kFunction, true})); TestParams{ast::AddressSpace::kFunction, true}));
} // namespace } // namespace
} // namespace tint::resolver } // namespace tint::resolver

View File

@ -28,14 +28,14 @@ using ResolverHostShareableValidationTest = ResolverTest;
TEST_F(ResolverHostShareableValidationTest, BoolMember) { TEST_F(ResolverHostShareableValidationTest, BoolMember) {
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.bool_())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.bool_())});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'storage' as it is non-host-shareable
12:34 note: while analysing structure member S.x 12:34 note: while analysing structure member S.x
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
@ -43,14 +43,14 @@ TEST_F(ResolverHostShareableValidationTest, BoolMember) {
TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) { TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) {
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.vec3<bool>())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.vec3<bool>())});
GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'vec3<bool>' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'vec3<bool>' cannot be used in address space 'storage' as it is non-host-shareable
12:34 note: while analysing structure member S.x 12:34 note: while analysing structure member S.x
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
@ -59,14 +59,14 @@ TEST_F(ResolverHostShareableValidationTest, Aliases) {
auto* a1 = Alias("a1", ty.bool_()); auto* a1 = Alias("a1", ty.bool_());
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.Of(a1))}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.Of(a1))});
auto* a2 = Alias("a2", ty.Of(s)); auto* a2 = Alias("a2", ty.Of(s));
GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable R"(56:78 error: Type 'bool' cannot be used in address space 'storage' as it is non-host-shareable
12:34 note: while analysing structure member S.x 12:34 note: while analysing structure member S.x
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
@ -78,14 +78,14 @@ TEST_F(ResolverHostShareableValidationTest, NestedStructures) {
auto* s = Structure("S", utils::Vector{Member(Source{{7, 8}}, "m", ty.Of(i3))}); auto* s = Structure("S", utils::Vector{Member(Source{{7, 8}}, "m", ty.Of(i3))});
GlobalVar(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{9, 10}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(9:10 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable R"(9:10 error: Type 'bool' cannot be used in address space 'storage' as it is non-host-shareable
1:2 note: while analysing structure member I1.x 1:2 note: while analysing structure member I1.x
3:4 note: while analysing structure member I2.y 3:4 note: while analysing structure member I2.y
5:6 note: while analysing structure member I3.z 5:6 note: while analysing structure member I3.z
@ -117,7 +117,7 @@ TEST_F(ResolverHostShareableValidationTest, NoError) {
auto* s = Structure("S", utils::Vector{Member(Source{{7, 8}}, "m", ty.Of(i3))}); auto* s = Structure("S", utils::Vector{Member(Source{{7, 8}}, "m", ty.Of(i3))});
GlobalVar(Source{{9, 10}}, "g", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{9, 10}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -64,8 +64,8 @@ TEST_F(ResolverIncrementDecrementValidationTest, ThroughPointer) {
// var a : i32; // var a : i32;
// let b : ptr<function,i32> = &a; // let b : ptr<function,i32> = &a;
// *b++; // *b++;
auto* var_a = Var("a", ty.i32(), ast::StorageClass::kFunction); auto* var_a = Var("a", ty.i32(), ast::AddressSpace::kFunction);
auto* var_b = Let("b", ty.pointer<i32>(ast::StorageClass::kFunction), AddressOf(Expr("a"))); auto* var_b = Let("b", ty.pointer<i32>(ast::AddressSpace::kFunction), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b, Increment(Source{{12, 34}}, Deref("b"))); WrapInFunction(var_a, var_b, Increment(Source{{12, 34}}, Deref("b")));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -127,7 +127,7 @@ TEST_F(ResolverIncrementDecrementValidationTest, Vector) {
TEST_F(ResolverIncrementDecrementValidationTest, Atomic) { TEST_F(ResolverIncrementDecrementValidationTest, Atomic) {
// var<workgroup> a : atomic<i32>; // var<workgroup> a : atomic<i32>;
// a++; // a++;
GlobalVar(Source{{12, 34}}, "a", ty.atomic(ty.i32()), ast::StorageClass::kWorkgroup); GlobalVar(Source{{12, 34}}, "a", ty.atomic(ty.i32()), ast::AddressSpace::kWorkgroup);
WrapInFunction(Increment(Expr(Source{{56, 78}}, "a"))); WrapInFunction(Increment(Expr(Source{{56, 78}}, "a")));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -193,7 +193,7 @@ TEST_F(ResolverIncrementDecrementValidationTest, ReadOnlyBuffer) {
// { // {
// a++; // a++;
// } // }
GlobalVar(Source{{12, 34}}, "a", ty.i32(), ast::StorageClass::kStorage, ast::Access::kRead, GlobalVar(Source{{12, 34}}, "a", ty.i32(), ast::AddressSpace::kStorage, ast::Access::kRead,
Group(0_a), Binding(0_a)); Group(0_a), Binding(0_a));
WrapInFunction(Increment(Source{{56, 78}}, "a")); WrapInFunction(Increment(Source{{56, 78}}, "a"));

View File

@ -97,7 +97,7 @@ TEST_P(ResolverInferredTypeParamTest, GlobalVar_Pass) {
// var a = <type constructor>; // var a = <type constructor>;
auto* ctor_expr = params.create_value(*this, 0); auto* ctor_expr = params.create_value(*this, 0);
auto* var = GlobalVar("a", ast::StorageClass::kPrivate, ctor_expr); auto* var = GlobalVar("a", ast::AddressSpace::kPrivate, ctor_expr);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type); EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
@ -124,7 +124,7 @@ TEST_P(ResolverInferredTypeParamTest, LocalVar_Pass) {
// var a = <type constructor>; // var a = <type constructor>;
auto* ctor_expr = params.create_value(*this, 0); auto* ctor_expr = params.create_value(*this, 0);
auto* var = Var("a", ast::StorageClass::kFunction, ctor_expr); auto* var = Var("a", ast::AddressSpace::kFunction, ctor_expr);
WrapInFunction(var); WrapInFunction(var);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -139,7 +139,7 @@ TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
create<sem::Array>(create<sem::U32>(), sem::ConstantArrayCount{10u}, 4u, 4u * 10u, 4u, 4u); create<sem::Array>(create<sem::U32>(), sem::ConstantArrayCount{10u}, 4u, 4u * 10u, 4u, 4u);
auto* ctor_expr = Construct(type); auto* ctor_expr = Construct(type);
auto* var = Var("a", ast::StorageClass::kFunction, ctor_expr); auto* var = Var("a", ast::AddressSpace::kFunction, ctor_expr);
WrapInFunction(var); WrapInFunction(var);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -158,7 +158,7 @@ TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
auto* ctor_expr = Construct(ty.Of(str)); auto* ctor_expr = Construct(ty.Of(str));
auto* var = Var("a", ast::StorageClass::kFunction, ctor_expr); auto* var = Var("a", ast::AddressSpace::kFunction, ctor_expr);
WrapInFunction(var); WrapInFunction(var);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -321,7 +321,7 @@ class TemplateNumberMatcher : public NumberMatcher {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
using TexelFormat = ast::TexelFormat; using TexelFormat = ast::TexelFormat;
using Access = ast::Access; using Access = ast::Access;
using StorageClass = ast::StorageClass; using AddressSpace = ast::AddressSpace;
using ParameterUsage = sem::ParameterUsage; using ParameterUsage = sem::ParameterUsage;
using PipelineStage = ast::PipelineStage; using PipelineStage = ast::PipelineStage;
@ -539,7 +539,7 @@ bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {
} }
if (auto* p = ty->As<sem::Pointer>()) { if (auto* p = ty->As<sem::Pointer>()) {
S = Number(static_cast<uint32_t>(p->StorageClass())); S = Number(static_cast<uint32_t>(p->AddressSpace()));
T = p->StoreType(); T = p->StoreType();
A = Number(static_cast<uint32_t>(p->Access())); A = Number(static_cast<uint32_t>(p->Access()));
return true; return true;
@ -548,7 +548,7 @@ bool match_ptr(const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {
} }
const sem::Pointer* build_ptr(MatchState& state, Number S, const sem::Type* T, Number& A) { const sem::Pointer* build_ptr(MatchState& state, Number S, const sem::Type* T, Number& A) {
return state.builder.create<sem::Pointer>(T, static_cast<ast::StorageClass>(S.Value()), return state.builder.create<sem::Pointer>(T, static_cast<ast::AddressSpace>(S.Value()),
static_cast<ast::Access>(A.Value())); static_cast<ast::Access>(A.Value()));
} }
@ -1158,7 +1158,7 @@ Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
params.Reserve(match.parameters.Length()); params.Reserve(match.parameters.Length());
for (auto& p : match.parameters) { for (auto& p : match.parameters) {
params.Push(builder.create<sem::Parameter>( params.Push(builder.create<sem::Parameter>(
nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::StorageClass::kNone, nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::AddressSpace::kNone,
ast::Access::kUndefined, p.usage)); ast::Access::kUndefined, p.usage));
} }
sem::PipelineStageSet supported_stages; sem::PipelineStageSet supported_stages;
@ -1356,7 +1356,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
params.Reserve(match.parameters.Length()); params.Reserve(match.parameters.Length());
for (auto& p : match.parameters) { for (auto& p : match.parameters) {
params.Push(builder.create<sem::Parameter>( params.Push(builder.create<sem::Parameter>(
nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::StorageClass::kNone, nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::AddressSpace::kNone,
ast::Access::kUndefined, p.usage)); ast::Access::kUndefined, p.usage));
} }
auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
@ -1371,7 +1371,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
// Conversion. // Conversion.
auto* target = utils::GetOrCreate(converters, match, [&]() { auto* target = utils::GetOrCreate(converters, match, [&]() {
auto param = builder.create<sem::Parameter>( auto param = builder.create<sem::Parameter>(
nullptr, 0u, match.parameters[0].type, ast::StorageClass::kNone, nullptr, 0u, match.parameters[0].type, ast::AddressSpace::kNone,
ast::Access::kUndefined, match.parameters[0].usage); ast::Access::kUndefined, match.parameters[0].usage);
auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
: sem::EvaluationStage::kRuntime; : sem::EvaluationStage::kRuntime;

View File

@ -2457,10 +2457,10 @@ class FunctionPrivateWorkgroup : public NumberMatcher {
}; };
Number FunctionPrivateWorkgroup::Match(MatchState&, Number number) const { Number FunctionPrivateWorkgroup::Match(MatchState&, Number number) const {
switch (static_cast<StorageClass>(number.Value())) { switch (static_cast<AddressSpace>(number.Value())) {
case StorageClass::kFunction: case AddressSpace::kFunction:
case StorageClass::kPrivate: case AddressSpace::kPrivate:
case StorageClass::kWorkgroup: case AddressSpace::kWorkgroup:
return number; return number;
default: default:
return Number::invalid; return Number::invalid;
@ -2486,9 +2486,9 @@ class WorkgroupOrStorage : public NumberMatcher {
}; };
Number WorkgroupOrStorage::Match(MatchState&, Number number) const { Number WorkgroupOrStorage::Match(MatchState&, Number number) const {
switch (static_cast<StorageClass>(number.Value())) { switch (static_cast<AddressSpace>(number.Value())) {
case StorageClass::kWorkgroup: case AddressSpace::kWorkgroup:
case StorageClass::kStorage: case AddressSpace::kStorage:
return number; return number;
default: default:
return Number::invalid; return Number::invalid;
@ -2514,8 +2514,8 @@ class Storage : public NumberMatcher {
}; };
Number Storage::Match(MatchState&, Number number) const { Number Storage::Match(MatchState&, Number number) const {
if (number.IsAny() || number.Value() == static_cast<uint32_t>(StorageClass::kStorage)) { if (number.IsAny() || number.Value() == static_cast<uint32_t>(AddressSpace::kStorage)) {
return Number(static_cast<uint32_t>(StorageClass::kStorage)); return Number(static_cast<uint32_t>(AddressSpace::kStorage));
} }
return Number::invalid; return Number::invalid;
} }

View File

@ -216,7 +216,7 @@ TEST_F(IntrinsicTableTest, MatchPointer) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* atomicI32 = create<sem::Atomic>(i32); auto* atomicI32 = create<sem::Atomic>(i32);
auto* ptr = auto* ptr =
create<sem::Pointer>(atomicI32, ast::StorageClass::kWorkgroup, ast::Access::kReadWrite); create<sem::Pointer>(atomicI32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr}, Source{}); auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr}, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str(); ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
@ -236,7 +236,7 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
TEST_F(IntrinsicTableTest, MatchArray) { TEST_F(IntrinsicTableTest, MatchArray) {
auto* arr = create<sem::Array>(create<sem::U32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u); auto* arr = create<sem::Array>(create<sem::U32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage, ast::Access::kReadWrite); auto* arr_ptr = create<sem::Pointer>(arr, ast::AddressSpace::kStorage, ast::Access::kReadWrite);
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr}, Source{}); auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr}, Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str(); ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), ""); ASSERT_EQ(Diagnostics().str(), "");
@ -424,7 +424,7 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
auto result = table->Lookup( auto result = table->Lookup(
BuiltinType::kCos, BuiltinType::kCos,
utils::Vector{ utils::Vector{
create<sem::Reference>(f32, ast::StorageClass::kFunction, ast::Access::kReadWrite), create<sem::Reference>(f32, ast::AddressSpace::kFunction, ast::Access::kReadWrite),
}, },
Source{}); Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str(); ASSERT_NE(result.sem, nullptr) << Diagnostics().str();

View File

@ -95,7 +95,7 @@ TEST_F(ResolverIsHostShareable, Matrix) {
} }
TEST_F(ResolverIsHostShareable, Pointer) { TEST_F(ResolverIsHostShareable, Pointer) {
auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::StorageClass::kPrivate, auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::AddressSpace::kPrivate,
ast::Access::kReadWrite); ast::Access::kReadWrite);
EXPECT_FALSE(r()->IsHostShareable(ptr)); EXPECT_FALSE(r()->IsHostShareable(ptr));
} }

View File

@ -78,7 +78,7 @@ TEST_F(ResolverIsStorableTest, Matrix) {
} }
TEST_F(ResolverIsStorableTest, Pointer) { TEST_F(ResolverIsStorableTest, Pointer) {
auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::StorageClass::kPrivate, auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::AddressSpace::kPrivate,
ast::Access::kReadWrite); ast::Access::kReadWrite);
EXPECT_FALSE(r()->IsStorable(ptr)); EXPECT_FALSE(r()->IsStorable(ptr));
} }
@ -111,7 +111,7 @@ TEST_F(ResolverIsStorableTest, Struct_AllMembersStorable) {
TEST_F(ResolverIsStorableTest, Struct_SomeMembersNonStorable) { TEST_F(ResolverIsStorableTest, Struct_SomeMembersNonStorable) {
Structure("S", utils::Vector{ Structure("S", utils::Vector{
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", ty.pointer<i32>(ast::StorageClass::kPrivate)), Member("b", ty.pointer<i32>(ast::AddressSpace::kPrivate)),
}); });
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -137,7 +137,7 @@ TEST_F(ResolverIsStorableTest, Struct_NestedNonStorable) {
auto* non_storable = auto* non_storable =
Structure("nonstorable", utils::Vector{ Structure("nonstorable", utils::Vector{
Member("a", ty.i32()), Member("a", ty.i32()),
Member("b", ty.pointer<i32>(ast::StorageClass::kPrivate)), Member("b", ty.pointer<i32>(ast::AddressSpace::kPrivate)),
}); });
Structure("S", utils::Vector{ Structure("S", utils::Vector{
Member("a", ty.i32()), Member("a", ty.i32()),

View File

@ -902,7 +902,7 @@ TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
utils::Vector{WorkgroupSize(abstract_expr()), Stage(ast::PipelineStage::kCompute)}); utils::Vector{WorkgroupSize(abstract_expr()), Stage(ast::PipelineStage::kCompute)});
break; break;
case Method::kIndex: case Method::kIndex:
GlobalVar("arr", ty.array<i32, 4>(), ast::StorageClass::kPrivate); GlobalVar("arr", ty.array<i32, 4>(), ast::AddressSpace::kPrivate);
WrapInFunction(IndexAccessor("arr", abstract_expr())); WrapInFunction(IndexAccessor("arr", abstract_expr()));
break; break;
case Method::kRuntimeIndex: case Method::kRuntimeIndex:

View File

@ -38,7 +38,7 @@ TEST_F(ResolverPtrRefTest, AddressOf) {
ASSERT_TRUE(TypeOf(expr)->Is<sem::Pointer>()); ASSERT_TRUE(TypeOf(expr)->Is<sem::Pointer>());
EXPECT_TRUE(TypeOf(expr)->As<sem::Pointer>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(expr)->As<sem::Pointer>()->StoreType()->Is<sem::I32>());
EXPECT_EQ(TypeOf(expr)->As<sem::Pointer>()->StorageClass(), ast::StorageClass::kFunction); EXPECT_EQ(TypeOf(expr)->As<sem::Pointer>()->AddressSpace(), ast::AddressSpace::kFunction);
} }
TEST_F(ResolverPtrRefTest, AddressOfThenDeref) { TEST_F(ResolverPtrRefTest, AddressOfThenDeref) {
@ -56,28 +56,28 @@ TEST_F(ResolverPtrRefTest, AddressOfThenDeref) {
EXPECT_TRUE(TypeOf(expr)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(expr)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
} }
TEST_F(ResolverPtrRefTest, DefaultPtrStorageClass) { TEST_F(ResolverPtrRefTest, DefaultPtrAddressSpace) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())}); auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())});
auto* function = Var("f", ty.i32()); auto* function = Var("f", ty.i32());
auto* private_ = GlobalVar("p", ty.i32(), ast::StorageClass::kPrivate); auto* private_ = GlobalVar("p", ty.i32(), ast::AddressSpace::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::StorageClass::kWorkgroup); auto* workgroup = GlobalVar("w", ty.i32(), ast::AddressSpace::kWorkgroup);
auto* uniform = auto* uniform =
GlobalVar("ub", ty.Of(buf), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("ub", ty.Of(buf), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
auto* storage = auto* storage =
GlobalVar("sb", ty.Of(buf), ast::StorageClass::kStorage, Binding(1_a), Group(0_a)); GlobalVar("sb", ty.Of(buf), ast::AddressSpace::kStorage, Binding(1_a), Group(0_a));
auto* function_ptr = auto* function_ptr =
Let("f_ptr", ty.pointer(ty.i32(), ast::StorageClass::kFunction), AddressOf(function)); Let("f_ptr", ty.pointer(ty.i32(), ast::AddressSpace::kFunction), AddressOf(function));
auto* private_ptr = auto* private_ptr =
Let("p_ptr", ty.pointer(ty.i32(), ast::StorageClass::kPrivate), AddressOf(private_)); Let("p_ptr", ty.pointer(ty.i32(), ast::AddressSpace::kPrivate), AddressOf(private_));
auto* workgroup_ptr = auto* workgroup_ptr =
Let("w_ptr", ty.pointer(ty.i32(), ast::StorageClass::kWorkgroup), AddressOf(workgroup)); Let("w_ptr", ty.pointer(ty.i32(), ast::AddressSpace::kWorkgroup), AddressOf(workgroup));
auto* uniform_ptr = auto* uniform_ptr =
Let("ub_ptr", ty.pointer(ty.Of(buf), ast::StorageClass::kUniform), AddressOf(uniform)); Let("ub_ptr", ty.pointer(ty.Of(buf), ast::AddressSpace::kUniform), AddressOf(uniform));
auto* storage_ptr = auto* storage_ptr =
Let("sb_ptr", ty.pointer(ty.Of(buf), ast::StorageClass::kStorage), AddressOf(storage)); Let("sb_ptr", ty.pointer(ty.Of(buf), ast::AddressSpace::kStorage), AddressOf(storage));
WrapInFunction(function, function_ptr, private_ptr, workgroup_ptr, uniform_ptr, storage_ptr); WrapInFunction(function, function_ptr, private_ptr, workgroup_ptr, uniform_ptr, storage_ptr);

View File

@ -62,7 +62,7 @@ TEST_F(ResolverPtrRefValidationTest, AddressOfHandle) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: cannot take the address of expression in handle " "12:34 error: cannot take the address of expression in handle "
"storage class"); "address space");
} }
TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_MemberAccessor) { TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_MemberAccessor) {
@ -102,7 +102,7 @@ TEST_F(ResolverPtrRefValidationTest, IndirectOfAddressOfHandle) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: cannot take the address of expression in handle " "12:34 error: cannot take the address of expression in handle "
"storage class"); "address space");
} }
TEST_F(ResolverPtrRefValidationTest, DerefOfLiteral) { TEST_F(ResolverPtrRefValidationTest, DerefOfLiteral) {
@ -143,12 +143,12 @@ TEST_F(ResolverPtrRefValidationTest, InferredPtrAccessMismatch) {
// } // }
auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())}); auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", utils::Vector{Member("inner", ty.Of(inner))}); auto* buf = Structure("S", utils::Vector{Member("inner", ty.Of(inner))});
auto* storage = GlobalVar("s", ty.Of(buf), ast::StorageClass::kStorage, ast::Access::kReadWrite, auto* storage = GlobalVar("s", ty.Of(buf), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 2_i); auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 2_i);
auto* ptr = auto* ptr =
Let(Source{{12, 34}}, "p", ty.pointer<i32>(ast::StorageClass::kStorage), AddressOf(expr)); Let(Source{{12, 34}}, "p", ty.pointer<i32>(ast::AddressSpace::kStorage), AddressOf(expr));
WrapInFunction(ptr); WrapInFunction(ptr);

View File

@ -247,9 +247,9 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
if (auto* el = Type(t->type)) { if (auto* el = Type(t->type)) {
auto access = t->access; auto access = t->access;
if (access == ast::kUndefined) { if (access == ast::kUndefined) {
access = DefaultAccessForStorageClass(t->storage_class); access = DefaultAccessForAddressSpace(t->address_space);
} }
return builder_->create<sem::Pointer>(el, t->storage_class, access); return builder_->create<sem::Pointer>(el, t->address_space, access);
} }
return nullptr; return nullptr;
}, },
@ -368,11 +368,11 @@ sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS
} }
if (rhs && !validator_.VariableInitializer(v, ast::StorageClass::kNone, ty, rhs)) { if (rhs && !validator_.VariableInitializer(v, ast::AddressSpace::kNone, ty, rhs)) {
return nullptr; return nullptr;
} }
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty), if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
v->source)) { v->source)) {
AddNote("while instantiating 'let' " + builder_->Symbols().NameFor(v->symbol), v->source); AddNote("while instantiating 'let' " + builder_->Symbols().NameFor(v->symbol), v->source);
return nullptr; return nullptr;
@ -381,12 +381,12 @@ sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
sem::Variable* sem = nullptr; sem::Variable* sem = nullptr;
if (is_global) { if (is_global) {
sem = builder_->create<sem::GlobalVariable>( sem = builder_->create<sem::GlobalVariable>(
v, ty, sem::EvaluationStage::kRuntime, ast::StorageClass::kNone, v, ty, sem::EvaluationStage::kRuntime, ast::AddressSpace::kNone,
ast::Access::kUndefined, /* constant_value */ nullptr, sem::BindingPoint{}, ast::Access::kUndefined, /* constant_value */ nullptr, sem::BindingPoint{},
std::nullopt); std::nullopt);
} else { } else {
sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime, sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime,
ast::StorageClass::kNone, ast::AddressSpace::kNone,
ast::Access::kUndefined, current_statement_, ast::Access::kUndefined, current_statement_,
/* constant_value */ nullptr); /* constant_value */ nullptr);
} }
@ -425,11 +425,11 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
return nullptr; return nullptr;
} }
if (rhs && !validator_.VariableInitializer(v, ast::StorageClass::kNone, ty, rhs)) { if (rhs && !validator_.VariableInitializer(v, ast::AddressSpace::kNone, ty, rhs)) {
return nullptr; return nullptr;
} }
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty), if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
v->source)) { v->source)) {
AddNote("while instantiating 'override' " + builder_->Symbols().NameFor(v->symbol), AddNote("while instantiating 'override' " + builder_->Symbols().NameFor(v->symbol),
v->source); v->source);
@ -437,7 +437,7 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
} }
auto* sem = builder_->create<sem::GlobalVariable>( auto* sem = builder_->create<sem::GlobalVariable>(
v, ty, sem::EvaluationStage::kOverride, ast::StorageClass::kNone, ast::Access::kUndefined, v, ty, sem::EvaluationStage::kOverride, ast::AddressSpace::kNone, ast::Access::kUndefined,
/* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt); /* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt);
sem->SetConstructor(rhs); sem->SetConstructor(rhs);
@ -510,21 +510,21 @@ sem::Variable* Resolver::Const(const ast::Const* c, bool is_global) {
return nullptr; return nullptr;
} }
if (!validator_.VariableInitializer(c, ast::StorageClass::kNone, ty, rhs)) { if (!validator_.VariableInitializer(c, ast::AddressSpace::kNone, ty, rhs)) {
return nullptr; return nullptr;
} }
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty), if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
c->source)) { c->source)) {
AddNote("while instantiating 'const' " + builder_->Symbols().NameFor(c->symbol), c->source); AddNote("while instantiating 'const' " + builder_->Symbols().NameFor(c->symbol), c->source);
return nullptr; return nullptr;
} }
auto* sem = is_global ? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>( auto* sem = is_global ? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>(
c, ty, sem::EvaluationStage::kConstant, ast::StorageClass::kNone, c, ty, sem::EvaluationStage::kConstant, ast::AddressSpace::kNone,
ast::Access::kUndefined, value, sem::BindingPoint{}, std::nullopt)) ast::Access::kUndefined, value, sem::BindingPoint{}, std::nullopt))
: static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>( : static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>(
c, ty, sem::EvaluationStage::kConstant, ast::StorageClass::kNone, c, ty, sem::EvaluationStage::kConstant, ast::AddressSpace::kNone,
ast::Access::kUndefined, current_statement_, value)); ast::Access::kUndefined, current_statement_, value));
sem->SetConstructor(rhs); sem->SetConstructor(rhs);
@ -562,39 +562,39 @@ sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
return nullptr; return nullptr;
} }
auto storage_class = var->declared_storage_class; auto address_space = var->declared_address_space;
if (storage_class == ast::StorageClass::kNone) { if (address_space == ast::AddressSpace::kNone) {
// No declared storage class. Infer from usage / type. // No declared address space. Infer from usage / type.
if (!is_global) { if (!is_global) {
storage_class = ast::StorageClass::kFunction; address_space = ast::AddressSpace::kFunction;
} else if (storage_ty->UnwrapRef()->is_handle()) { } else if (storage_ty->UnwrapRef()->is_handle()) {
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the // If the store type is a texture type or a sampler type, then the
// variable declaration must not have a storage class attribute. The // variable declaration must not have a address space attribute. The
// storage class will always be handle. // address space will always be handle.
storage_class = ast::StorageClass::kHandle; address_space = ast::AddressSpace::kHandle;
} }
} }
if (!is_global && storage_class != ast::StorageClass::kFunction && if (!is_global && address_space != ast::AddressSpace::kFunction &&
validator_.IsValidationEnabled(var->attributes, validator_.IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreStorageClass)) { ast::DisabledValidation::kIgnoreAddressSpace)) {
AddError("function-scope 'var' declaration must use 'function' storage class", var->source); AddError("function-scope 'var' declaration must use 'function' address space", var->source);
return nullptr; return nullptr;
} }
auto access = var->declared_access; auto access = var->declared_access;
if (access == ast::Access::kUndefined) { if (access == ast::Access::kUndefined) {
access = DefaultAccessForStorageClass(storage_class); access = DefaultAccessForAddressSpace(address_space);
} }
if (rhs && !validator_.VariableInitializer(var, storage_class, storage_ty, rhs)) { if (rhs && !validator_.VariableInitializer(var, address_space, storage_ty, rhs)) {
return nullptr; return nullptr;
} }
auto* var_ty = builder_->create<sem::Reference>(storage_ty, storage_class, access); auto* var_ty = builder_->create<sem::Reference>(storage_ty, address_space, access);
if (!ApplyStorageClassUsageToType(storage_class, var_ty, var->source)) { if (!ApplyAddressSpaceUsageToType(address_space, var_ty, var->source)) {
AddNote("while instantiating 'var' " + builder_->Symbols().NameFor(var->symbol), AddNote("while instantiating 'var' " + builder_->Symbols().NameFor(var->symbol),
var->source); var->source);
return nullptr; return nullptr;
@ -654,12 +654,12 @@ sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
} }
sem = builder_->create<sem::GlobalVariable>( sem = builder_->create<sem::GlobalVariable>(
var, var_ty, sem::EvaluationStage::kRuntime, storage_class, access, var, var_ty, sem::EvaluationStage::kRuntime, address_space, access,
/* constant_value */ nullptr, binding_point, location); /* constant_value */ nullptr, binding_point, location);
} else { } else {
sem = builder_->create<sem::LocalVariable>(var, var_ty, sem::EvaluationStage::kRuntime, sem = builder_->create<sem::LocalVariable>(var, var_ty, sem::EvaluationStage::kRuntime,
storage_class, access, current_statement_, address_space, access, current_statement_,
/* constant_value */ nullptr); /* constant_value */ nullptr);
} }
@ -686,7 +686,7 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
return nullptr; return nullptr;
} }
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, ty, param->source)) { if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, ty, param->source)) {
add_note(); add_note();
return nullptr; return nullptr;
} }
@ -694,8 +694,8 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
if (auto* ptr = ty->As<sem::Pointer>()) { if (auto* ptr = ty->As<sem::Pointer>()) {
// For MSL, we push module-scope variables into the entry point as pointer // For MSL, we push module-scope variables into the entry point as pointer
// parameters, so we also need to handle their store type. // parameters, so we also need to handle their store type.
if (!ApplyStorageClassUsageToType( if (!ApplyAddressSpaceUsageToType(
ptr->StorageClass(), const_cast<sem::Type*>(ptr->StoreType()), param->source)) { ptr->AddressSpace(), const_cast<sem::Type*>(ptr->StoreType()), param->source)) {
add_note(); add_note();
return nullptr; return nullptr;
} }
@ -749,18 +749,18 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
} }
auto* sem = builder_->create<sem::Parameter>( auto* sem = builder_->create<sem::Parameter>(
param, index, ty, ast::StorageClass::kNone, ast::Access::kUndefined, param, index, ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
sem::ParameterUsage::kNone, binding_point, location); sem::ParameterUsage::kNone, binding_point, location);
builder_->Sem().Add(param, sem); builder_->Sem().Add(param, sem);
return sem; return sem;
} }
ast::Access Resolver::DefaultAccessForStorageClass(ast::StorageClass storage_class) { ast::Access Resolver::DefaultAccessForAddressSpace(ast::AddressSpace address_space) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
switch (storage_class) { switch (address_space) {
case ast::StorageClass::kStorage: case ast::AddressSpace::kStorage:
case ast::StorageClass::kUniform: case ast::AddressSpace::kUniform:
case ast::StorageClass::kHandle: case ast::AddressSpace::kHandle:
return ast::Access::kRead; return ast::Access::kRead;
default: default:
break; break;
@ -845,7 +845,7 @@ sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* v) {
// TODO(bclayton): Call this at the end of resolve on all uniform and storage // TODO(bclayton): Call this at the end of resolve on all uniform and storage
// referenced structs // referenced structs
if (!validator_.StorageClassLayout(sem, enabled_extensions_, valid_type_storage_layouts_)) { if (!validator_.AddressSpaceLayout(sem, enabled_extensions_, valid_type_storage_layouts_)) {
return nullptr; return nullptr;
} }
@ -962,7 +962,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
} }
if (auto* str = return_type->As<sem::Struct>()) { if (auto* str = return_type->As<sem::Struct>()) {
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, str, decl->source)) { if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, str, decl->source)) {
AddNote( AddNote(
"while instantiating return type for " + builder_->Symbols().NameFor(decl->symbol), "while instantiating return type for " + builder_->Symbols().NameFor(decl->symbol),
decl->source); decl->source);
@ -1625,7 +1625,7 @@ sem::Expression* Resolver::IndexAccessor(const ast::IndexAccessorExpression* exp
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = obj_raw_ty->As<sem::Reference>()) { if (auto* ref = obj_raw_ty->As<sem::Reference>()) {
ty = builder_->create<sem::Reference>(ty, ref->StorageClass(), ref->Access()); ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
} }
auto stage = sem::EarliestStage(obj->Stage(), idx->Stage()); auto stage = sem::EarliestStage(obj->Stage(), idx->Stage());
@ -1783,7 +1783,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
nullptr, // declaration nullptr, // declaration
static_cast<uint32_t>(i), // index static_cast<uint32_t>(i), // index
arr->ElemType(), // type arr->ElemType(), // type
ast::StorageClass::kNone, // storage_class ast::AddressSpace::kNone, // address_space
ast::Access::kUndefined); ast::Access::kUndefined);
}); });
return builder_->create<sem::TypeConstructor>(arr, std::move(params), return builder_->create<sem::TypeConstructor>(arr, std::move(params),
@ -1812,7 +1812,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
nullptr, // declaration nullptr, // declaration
static_cast<uint32_t>(i), // index static_cast<uint32_t>(i), // index
str->Members()[i]->Type(), // type str->Members()[i]->Type(), // type
ast::StorageClass::kNone, // storage_class ast::AddressSpace::kNone, // address_space
ast::Access::kUndefined); // access ast::Access::kUndefined); // access
} }
return builder_->create<sem::TypeConstructor>(str, std::move(params), return builder_->create<sem::TypeConstructor>(str, std::move(params),
@ -2321,7 +2321,7 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = structure->As<sem::Reference>()) { if (auto* ref = structure->As<sem::Reference>()) {
ty = builder_->create<sem::Reference>(ty, ref->StorageClass(), ref->Access()); ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
} }
auto val = const_eval_.MemberAccess(object, member); auto val = const_eval_.MemberAccess(object, member);
@ -2390,7 +2390,7 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
ty = vec->type(); ty = vec->type();
// If we're extracting from a reference, we return a reference. // If we're extracting from a reference, we return a reference.
if (auto* ref = structure->As<sem::Reference>()) { if (auto* ref = structure->As<sem::Reference>()) {
ty = builder_->create<sem::Reference>(ty, ref->StorageClass(), ref->Access()); ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
} }
} else { } else {
// The vector will have a number of components equal to the length of // The vector will have a number of components equal to the length of
@ -2483,7 +2483,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
case ast::UnaryOp::kAddressOf: case ast::UnaryOp::kAddressOf:
if (auto* ref = expr_ty->As<sem::Reference>()) { if (auto* ref = expr_ty->As<sem::Reference>()) {
if (ref->StoreType()->UnwrapRef()->is_handle()) { if (ref->StoreType()->UnwrapRef()->is_handle()) {
AddError("cannot take the address of expression in handle storage class", AddError("cannot take the address of expression in handle address space",
unary->expr->source); unary->expr->source);
return nullptr; return nullptr;
} }
@ -2496,7 +2496,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
return nullptr; return nullptr;
} }
ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->StorageClass(), ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(),
ref->Access()); ref->Access());
source_var = expr->SourceVariable(); source_var = expr->SourceVariable();
@ -2508,7 +2508,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
case ast::UnaryOp::kIndirection: case ast::UnaryOp::kIndirection:
if (auto* ptr = expr_ty->As<sem::Pointer>()) { if (auto* ptr = expr_ty->As<sem::Pointer>()) {
ty = builder_->create<sem::Reference>(ptr->StoreType(), ptr->StorageClass(), ty = builder_->create<sem::Reference>(ptr->StoreType(), ptr->AddressSpace(),
ptr->Access()); ptr->Access());
source_var = expr->SourceVariable(); source_var = expr->SourceVariable();
} else { } else {
@ -3205,20 +3205,20 @@ sem::Statement* Resolver::IncrementDecrementStatement(
}); });
} }
bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc, bool Resolver::ApplyAddressSpaceUsageToType(ast::AddressSpace sc,
sem::Type* ty, sem::Type* ty,
const Source& usage) { const Source& usage) {
ty = const_cast<sem::Type*>(ty->UnwrapRef()); ty = const_cast<sem::Type*>(ty->UnwrapRef());
if (auto* str = ty->As<sem::Struct>()) { if (auto* str = ty->As<sem::Struct>()) {
if (str->StorageClassUsage().count(sc)) { if (str->AddressSpaceUsage().count(sc)) {
return true; // Already applied return true; // Already applied
} }
str->AddUsage(sc); str->AddUsage(sc);
for (auto* member : str->Members()) { for (auto* member : str->Members()) {
if (!ApplyStorageClassUsageToType(sc, const_cast<sem::Type*>(member->Type()), usage)) { if (!ApplyAddressSpaceUsageToType(sc, const_cast<sem::Type*>(member->Type()), usage)) {
std::stringstream err; std::stringstream err;
err << "while analysing structure member " << sem_.TypeNameOf(str) << "." err << "while analysing structure member " << sem_.TypeNameOf(str) << "."
<< builder_->Symbols().NameFor(member->Declaration()->symbol); << builder_->Symbols().NameFor(member->Declaration()->symbol);
@ -3230,20 +3230,20 @@ bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc,
} }
if (auto* arr = ty->As<sem::Array>()) { if (auto* arr = ty->As<sem::Array>()) {
if (arr->IsRuntimeSized() && sc != ast::StorageClass::kStorage) { if (arr->IsRuntimeSized() && sc != ast::AddressSpace::kStorage) {
AddError( AddError(
"runtime-sized arrays can only be used in the <storage> storage " "runtime-sized arrays can only be used in the <storage> address "
"class", "space",
usage); usage);
return false; return false;
} }
return ApplyStorageClassUsageToType(sc, const_cast<sem::Type*>(arr->ElemType()), usage); return ApplyAddressSpaceUsageToType(sc, const_cast<sem::Type*>(arr->ElemType()), usage);
} }
if (ast::IsHostShareable(sc) && !validator_.IsHostShareable(ty)) { if (ast::IsHostShareable(sc) && !validator_.IsHostShareable(ty)) {
std::stringstream err; std::stringstream err;
err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in storage class '" << sc err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in address space '" << sc
<< "' as it is non-host-shareable"; << "' as it is non-host-shareable";
AddError(err.str(), usage); AddError(err.str(), usage);
return false; return false;

View File

@ -387,20 +387,20 @@ class Resolver {
/// @param index the index of the parameter /// @param index the index of the parameter
sem::Parameter* Parameter(const ast::Parameter* param, uint32_t index); sem::Parameter* Parameter(const ast::Parameter* param, uint32_t index);
/// Records the storage class usage for the given type, and any transient /// Records the address space usage for the given type, and any transient
/// dependencies of the type. Validates that the type can be used for the /// dependencies of the type. Validates that the type can be used for the
/// given storage class, erroring if it cannot. /// given address space, erroring if it cannot.
/// @param sc the storage class to apply to the type and transitent types /// @param sc the address space to apply to the type and transitent types
/// @param ty the type to apply the storage class on /// @param ty the type to apply the address space on
/// @param usage the Source of the root variable declaration that uses the /// @param usage the Source of the root variable declaration that uses the
/// given type and storage class. Used for generating sensible error /// given type and address space. Used for generating sensible error
/// messages. /// messages.
/// @returns true on success, false on error /// @returns true on success, false on error
bool ApplyStorageClassUsageToType(ast::StorageClass sc, sem::Type* ty, const Source& usage); bool ApplyAddressSpaceUsageToType(ast::AddressSpace sc, sem::Type* ty, const Source& usage);
/// @param storage_class the storage class /// @param address_space the address space
/// @returns the default access control for the given storage class /// @returns the default access control for the given address space
ast::Access DefaultAccessForStorageClass(ast::StorageClass storage_class); ast::Access DefaultAccessForAddressSpace(ast::AddressSpace address_space);
/// Allocate constant IDs for pipeline-overridable constants. /// Allocate constant IDs for pipeline-overridable constants.
/// @returns true on success, false on error /// @returns true on success, false on error

View File

@ -1,78 +0,0 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/resolver/resolver.h"
#include "gmock/gmock.h"
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/sem/atomic.h"
namespace tint::resolver {
namespace {
using ResolverIsStorableTest = ResolverTest;
TEST_F(ResolverIsStorableTest, Struct_AllMembersStorable) {
Structure("S", {
Member("a", ty.i32()),
Member("b", ty.f32()),
});
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverIsStorableTest, Struct_SomeMembersNonStorable) {
Structure("S", {
Member("a", ty.i32()),
Member("b", ty.pointer<i32>(ast::StorageClass::kPrivate)),
});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(error: ptr<private, i32, read_write> cannot be used as the type of a structure member)");
}
TEST_F(ResolverIsStorableTest, Struct_NestedStorable) {
auto* storable = Structure("Storable", {
Member("a", ty.i32()),
Member("b", ty.f32()),
});
Structure("S", {
Member("a", ty.i32()),
Member("b", ty.Of(storable)),
});
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverIsStorableTest, Struct_NestedNonStorable) {
auto* non_storable =
Structure("nonstorable", {
Member("a", ty.i32()),
Member("b", ty.pointer<i32>(ast::StorageClass::kPrivate)),
});
Structure("S", {
Member("a", ty.i32()),
Member("b", ty.Of(non_storable)),
});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(error: ptr<private, i32, read_write> cannot be used as the type of a structure member)");
}
} // namespace
} // namespace tint::resolver

View File

@ -316,7 +316,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) { TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) {
auto* init = Expr(2_i); auto* init = Expr(2_i);
GlobalVar("my_var", ty.i32(), ast::StorageClass::kPrivate, init); GlobalVar("my_var", ty.i32(), ast::AddressSpace::kPrivate, init);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -396,7 +396,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
Func("func_i32", utils::Empty, ty.void_(), utils::Vector{fn_i32_decl}); Func("func_i32", utils::Empty, ty.void_(), utils::Vector{fn_i32_decl});
// Declare f32 "foo" at module scope // Declare f32 "foo" at module scope
auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kPrivate, Expr(2_f)); auto* mod_f32 = Var("foo", ty.f32(), ast::AddressSpace::kPrivate, Expr(2_f));
auto* mod_init = mod_f32->constructor; auto* mod_init = mod_f32->constructor;
AST().AddGlobalVariable(mod_f32); AST().AddGlobalVariable(mod_f32);
@ -424,7 +424,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
TEST_F(ResolverTest, ArraySize_UnsignedLiteral) { TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
// var<private> a : array<f32, 10u>; // var<private> a : array<f32, 10u>;
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr(10_u)), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr(10_u)), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -437,7 +437,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
TEST_F(ResolverTest, ArraySize_SignedLiteral) { TEST_F(ResolverTest, ArraySize_SignedLiteral) {
// var<private> a : array<f32, 10i>; // var<private> a : array<f32, 10i>;
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr(10_i)), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr(10_i)), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -452,7 +452,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedConst) {
// const size = 10u; // const size = 10u;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(10_u)); GlobalConst("size", Expr(10_u));
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -467,7 +467,7 @@ TEST_F(ResolverTest, ArraySize_SignedConst) {
// const size = 0; // const size = 0;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(10_i)); GlobalConst("size", Expr(10_i));
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -482,7 +482,7 @@ TEST_F(ResolverTest, ArraySize_Override) {
// override size = 0; // override size = 0;
// var<workgroup> a : array<f32, size>; // var<workgroup> a : array<f32, size>;
auto* override = Override("size", Expr(10_i)); auto* override = Override("size", Expr(10_i));
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kWorkgroup); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -500,8 +500,8 @@ TEST_F(ResolverTest, ArraySize_Override_Equivalence) {
// var<workgroup> a : array<f32, size>; // var<workgroup> a : array<f32, size>;
// var<workgroup> b : array<f32, size>; // var<workgroup> b : array<f32, size>;
auto* override = Override("size", Expr(10_i)); auto* override = Override("size", Expr(10_i));
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kWorkgroup); auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::AddressSpace::kWorkgroup);
auto* b = GlobalVar("b", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kWorkgroup); auto* b = GlobalVar("b", ty.array(ty.f32(), Expr("size")), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -523,7 +523,7 @@ TEST_F(ResolverTest, ArraySize_Override_Equivalence) {
} }
TEST_F(ResolverTest, Expr_Bitcast) { TEST_F(ResolverTest, Expr_Bitcast) {
GlobalVar("name", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("name", ty.f32(), ast::AddressSpace::kPrivate);
auto* bitcast = create<ast::BitcastExpression>(ty.f32(), Expr("name")); auto* bitcast = create<ast::BitcastExpression>(ty.f32(), Expr("name"));
WrapInFunction(bitcast); WrapInFunction(bitcast);
@ -586,7 +586,7 @@ TEST_F(ResolverTest, Expr_Call_Builtin) {
} }
TEST_F(ResolverTest, Expr_Cast) { TEST_F(ResolverTest, Expr_Cast) {
GlobalVar("name", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("name", ty.f32(), ast::AddressSpace::kPrivate);
auto* cast = Construct(ty.f32(), "name"); auto* cast = Construct(ty.f32(), "name");
WrapInFunction(cast); WrapInFunction(cast);
@ -644,7 +644,7 @@ TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) {
} }
TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) { TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) {
auto* my_var = GlobalVar("my_var", ty.f32(), ast::StorageClass::kPrivate); auto* my_var = GlobalVar("my_var", ty.f32(), ast::AddressSpace::kPrivate);
auto* ident = Expr("my_var"); auto* ident = Expr("my_var");
WrapInFunction(ident); WrapInFunction(ident);
@ -747,7 +747,7 @@ TEST_F(ResolverTest, Expr_Identifier_Function_Ptr) {
auto* v = Expr("v"); auto* v = Expr("v");
auto* p = Expr("p"); auto* p = Expr("p");
auto* v_decl = Decl(Var("v", ty.f32())); auto* v_decl = Decl(Var("v", ty.f32()));
auto* p_decl = Decl(Let("p", ty.pointer<f32>(ast::StorageClass::kFunction), AddressOf(v))); auto* p_decl = Decl(Let("p", ty.pointer<f32>(ast::AddressSpace::kFunction), AddressOf(v)));
auto* assign = Assign(Deref(p), 1.23_f); auto* assign = Assign(Deref(p), 1.23_f);
Func("my_func", utils::Empty, ty.void_(), Func("my_func", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -822,7 +822,7 @@ TEST_F(ResolverTest, Function_Parameters_Locations) {
auto* param_b = Param("b", ty.u32(), utils::Vector{Builtin(ast::BuiltinValue::kVertexIndex)}); auto* param_b = Param("b", ty.u32(), utils::Vector{Builtin(ast::BuiltinValue::kVertexIndex)});
auto* param_c = Param("c", ty.u32(), utils::Vector{Location(1_a)}); auto* param_c = Param("c", ty.u32(), utils::Vector{Location(1_a)});
GlobalVar("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* func = Func("my_func", auto* func = Func("my_func",
utils::Vector{ utils::Vector{
param_a, param_a,
@ -852,8 +852,8 @@ TEST_F(ResolverTest, Function_Parameters_Locations) {
TEST_F(ResolverTest, Function_GlobalVariable_Location) { TEST_F(ResolverTest, Function_GlobalVariable_Location) {
auto* var = GlobalVar( auto* var = GlobalVar(
"my_vec", ty.vec4<f32>(), ast::StorageClass::kIn, "my_vec", ty.vec4<f32>(), ast::AddressSpace::kIn,
utils::Vector{Location(3_a), Disable(ast::DisabledValidation::kIgnoreStorageClass)}); utils::Vector{Location(3_a), Disable(ast::DisabledValidation::kIgnoreAddressSpace)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -865,10 +865,10 @@ TEST_F(ResolverTest, Function_GlobalVariable_Location) {
TEST_F(ResolverTest, Function_RegisterInputOutputVariables) { TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
auto* s = Structure("S", utils::Vector{Member("m", ty.u32())}); auto* s = Structure("S", utils::Vector{Member("m", ty.u32())});
auto* sb_var = GlobalVar("sb_var", ty.Of(s), ast::StorageClass::kStorage, auto* sb_var = GlobalVar("sb_var", ty.Of(s), ast::AddressSpace::kStorage,
ast::Access::kReadWrite, Binding(0_a), Group(0_a)); ast::Access::kReadWrite, Binding(0_a), Group(0_a));
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::StorageClass::kWorkgroup); auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::StorageClass::kPrivate); auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::AddressSpace::kPrivate);
auto* func = Func("my_func", utils::Empty, ty.void_(), auto* func = Func("my_func", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -911,7 +911,7 @@ TEST_F(ResolverTest, Function_ReturnType_Location) {
} }
TEST_F(ResolverTest, Function_ReturnType_NoLocation) { TEST_F(ResolverTest, Function_ReturnType_NoLocation) {
GlobalVar("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* func = Func("my_func", utils::Empty, ty.vec4<f32>(), auto* func = Func("my_func", utils::Empty, ty.vec4<f32>(),
utils::Vector{ utils::Vector{
Return("my_vec"), Return("my_vec"),
@ -933,10 +933,10 @@ TEST_F(ResolverTest, Function_ReturnType_NoLocation) {
TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) { TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) {
auto* s = Structure("S", utils::Vector{Member("m", ty.u32())}); auto* s = Structure("S", utils::Vector{Member("m", ty.u32())});
auto* sb_var = GlobalVar("sb_var", ty.Of(s), ast::StorageClass::kStorage, auto* sb_var = GlobalVar("sb_var", ty.Of(s), ast::AddressSpace::kStorage,
ast::Access::kReadWrite, Binding(0_a), Group(0_a)); ast::Access::kReadWrite, Binding(0_a), Group(0_a));
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::StorageClass::kWorkgroup); auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::StorageClass::kPrivate); auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::AddressSpace::kPrivate);
Func("my_func", utils::Empty, ty.f32(), Func("my_func", utils::Empty, ty.f32(),
utils::Vector{Assign("wg_var", "wg_var"), Assign("sb_var", "sb_var"), utils::Vector{Assign("wg_var", "wg_var"), Assign("sb_var", "sb_var"),
@ -1187,7 +1187,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) {
TEST_F(ResolverTest, Expr_MemberAccessor_Struct) { TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
auto* st = Structure( auto* st = Structure(
"S", utils::Vector{Member("first_member", ty.i32()), Member("second_member", ty.f32())}); "S", utils::Vector{Member("first_member", ty.i32()), Member("second_member", ty.f32())});
GlobalVar("my_struct", ty.Of(st), ast::StorageClass::kPrivate); GlobalVar("my_struct", ty.Of(st), ast::AddressSpace::kPrivate);
auto* mem = MemberAccessor("my_struct", "second_member"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -1211,7 +1211,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
auto* st = Structure( auto* st = Structure(
"S", utils::Vector{Member("first_member", ty.i32()), Member("second_member", ty.f32())}); "S", utils::Vector{Member("first_member", ty.i32()), Member("second_member", ty.f32())});
auto* alias = Alias("alias", ty.Of(st)); auto* alias = Alias("alias", ty.Of(st));
GlobalVar("my_struct", ty.Of(alias), ast::StorageClass::kPrivate); GlobalVar("my_struct", ty.Of(alias), ast::AddressSpace::kPrivate);
auto* mem = MemberAccessor("my_struct", "second_member"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -1231,7 +1231,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
} }
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
GlobalVar("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* mem = MemberAccessor("my_vec", "xzyw"); auto* mem = MemberAccessor("my_vec", "xzyw");
WrapInFunction(mem); WrapInFunction(mem);
@ -1249,7 +1249,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
} }
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) {
GlobalVar("my_vec", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* mem = MemberAccessor("my_vec", "b"); auto* mem = MemberAccessor("my_vec", "b");
WrapInFunction(mem); WrapInFunction(mem);
@ -1285,7 +1285,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
auto* stB = Structure("B", utils::Vector{Member("foo", ty.vec4<f32>())}); auto* stB = Structure("B", utils::Vector{Member("foo", ty.vec4<f32>())});
auto* stA = Structure("A", utils::Vector{Member("mem", ty.array(ty.Of(stB), 3_i))}); auto* stA = Structure("A", utils::Vector{Member("mem", ty.array(ty.Of(stB), 3_i))});
GlobalVar("c", ty.Of(stA), ast::StorageClass::kPrivate); GlobalVar("c", ty.Of(stA), ast::AddressSpace::kPrivate);
auto* mem = auto* mem =
MemberAccessor(MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0_i), "foo"), "yx"); MemberAccessor(MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0_i), "foo"), "yx");
@ -1303,7 +1303,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) { TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) {
auto* st = Structure( auto* st = Structure(
"S", utils::Vector{Member("first_member", ty.f32()), Member("second_member", ty.f32())}); "S", utils::Vector{Member("first_member", ty.f32()), Member("second_member", ty.f32())});
GlobalVar("my_struct", ty.Of(st), ast::StorageClass::kPrivate); GlobalVar("my_struct", ty.Of(st), ast::AddressSpace::kPrivate);
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"));
@ -1606,8 +1606,8 @@ TEST_P(Expr_Binary_Test_Valid, All) {
ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type); ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type);
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate); GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate); GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs")); auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1641,8 +1641,8 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) {
<< FriendlyName(rhs_type); << FriendlyName(rhs_type);
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate); GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate); GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs")); auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1687,8 +1687,8 @@ TEST_P(Expr_Binary_Test_Invalid, All) {
ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type); ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type);
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate); GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate); GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, op, Expr("lhs"), Expr("rhs")); auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1727,8 +1727,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) {
is_valid_expr = vec_size == mat_cols; is_valid_expr = vec_size == mat_cols;
} }
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate); GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate); GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1764,8 +1764,8 @@ TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) {
auto* col = create<sem::Vector>(f32, lhs_mat_rows); auto* col = create<sem::Vector>(f32, lhs_mat_rows);
auto* result_type = create<sem::Matrix>(col, rhs_mat_cols); auto* result_type = create<sem::Matrix>(col, rhs_mat_cols);
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate); GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate); GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1793,11 +1793,11 @@ TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
auto op = GetParam(); auto op = GetParam();
if (op == ast::UnaryOp::kNot) { if (op == ast::UnaryOp::kNot) {
GlobalVar("ident", ty.vec4<bool>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<bool>(), ast::AddressSpace::kPrivate);
} else if (op == ast::UnaryOp::kNegation || op == ast::UnaryOp::kComplement) { } else if (op == ast::UnaryOp::kNegation || op == ast::UnaryOp::kComplement) {
GlobalVar("ident", ty.vec4<i32>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<i32>(), ast::AddressSpace::kPrivate);
} else { } else {
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
} }
auto* der = create<ast::UnaryOpExpression>(op, Expr("ident")); auto* der = create<ast::UnaryOpExpression>(op, Expr("ident"));
WrapInFunction(der); WrapInFunction(der);
@ -1821,7 +1821,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
ast::UnaryOp::kNegation, ast::UnaryOp::kNegation,
ast::UnaryOp::kNot)); ast::UnaryOp::kNot));
TEST_F(ResolverTest, StorageClass_SetsIfMissing) { TEST_F(ResolverTest, AddressSpace_SetsIfMissing) {
auto* var = Var("var", ty.i32()); auto* var = Var("var", ty.i32());
auto* stmt = Decl(var); auto* stmt = Decl(var);
@ -1829,42 +1829,42 @@ TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kFunction); EXPECT_EQ(Sem().Get(var)->AddressSpace(), ast::AddressSpace::kFunction);
} }
TEST_F(ResolverTest, StorageClass_SetForSampler) { TEST_F(ResolverTest, AddressSpace_SetForSampler) {
auto* t = ty.sampler(ast::SamplerKind::kSampler); auto* t = ty.sampler(ast::SamplerKind::kSampler);
auto* var = GlobalVar("var", t, Binding(0_a), Group(0_a)); auto* var = GlobalVar("var", t, Binding(0_a), Group(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kHandle); EXPECT_EQ(Sem().Get(var)->AddressSpace(), ast::AddressSpace::kHandle);
} }
TEST_F(ResolverTest, StorageClass_SetForTexture) { TEST_F(ResolverTest, AddressSpace_SetForTexture) {
auto* t = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32()); auto* t = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32());
auto* var = GlobalVar("var", t, Binding(0_a), Group(0_a)); auto* var = GlobalVar("var", t, Binding(0_a), Group(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kHandle); EXPECT_EQ(Sem().Get(var)->AddressSpace(), ast::AddressSpace::kHandle);
} }
TEST_F(ResolverTest, StorageClass_DoesNotSetOnConst) { TEST_F(ResolverTest, AddressSpace_DoesNotSetOnConst) {
auto* var = Let("var", ty.i32(), Construct(ty.i32())); auto* var = Let("var", ty.i32(), Construct(ty.i32()));
auto* stmt = Decl(var); auto* stmt = Decl(var);
Func("func", utils::Empty, ty.void_(), utils::Vector{stmt}); Func("func", utils::Empty, ty.void_(), utils::Vector{stmt});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kNone); EXPECT_EQ(Sem().Get(var)->AddressSpace(), ast::AddressSpace::kNone);
} }
TEST_F(ResolverTest, Access_SetForStorageBuffer) { TEST_F(ResolverTest, Access_SetForStorageBuffer) {
// struct S { x : i32 }; // struct S { x : i32 };
// var<storage> g : S; // var<storage> g : S;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())}); auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
auto* var = GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage, auto* var = GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -1897,11 +1897,11 @@ TEST_F(ResolverTest, Function_EntryPoints_StageAttribute) {
// ep_1 -> {} // ep_1 -> {}
// ep_2 -> {} // ep_2 -> {}
GlobalVar("first", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("first", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("second", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("second", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_a", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("call_a", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_b", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("call_b", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_c", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("call_c", ty.f32(), ast::AddressSpace::kPrivate);
auto* func_b = Func("b", utils::Empty, ty.f32(), auto* func_b = Func("b", utils::Empty, ty.f32(),
utils::Vector{ utils::Vector{
@ -2041,8 +2041,8 @@ TEST_F(ResolverTest, ASTNodeReachedTwice) {
{ {
ProgramBuilder b; ProgramBuilder b;
auto* expr = b.Expr(1_i); auto* expr = b.Expr(1_i);
b.GlobalVar("a", b.ty.i32(), ast::StorageClass::kPrivate, expr); b.GlobalVar("a", b.ty.i32(), ast::AddressSpace::kPrivate, expr);
b.GlobalVar("b", b.ty.i32(), ast::StorageClass::kPrivate, expr); b.GlobalVar("b", b.ty.i32(), ast::AddressSpace::kPrivate, expr);
Resolver(&b).Resolve(); Resolver(&b).Resolve();
}, },
"internal compiler error: AST node 'tint::ast::IntLiteralExpression' was encountered twice " "internal compiler error: AST node 'tint::ast::IntLiteralExpression' was encountered twice "
@ -2050,7 +2050,7 @@ TEST_F(ResolverTest, ASTNodeReachedTwice) {
} }
TEST_F(ResolverTest, UnaryOp_Not) { TEST_F(ResolverTest, UnaryOp_Not) {
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* der = create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(Source{{12, 34}}, "ident")); auto* der = create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(Source{{12, 34}}, "ident"));
WrapInFunction(der); WrapInFunction(der);
@ -2059,7 +2059,7 @@ TEST_F(ResolverTest, UnaryOp_Not) {
} }
TEST_F(ResolverTest, UnaryOp_Complement) { TEST_F(ResolverTest, UnaryOp_Complement) {
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* der = auto* der =
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr(Source{{12, 34}}, "ident")); create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr(Source{{12, 34}}, "ident"));
WrapInFunction(der); WrapInFunction(der);
@ -2069,7 +2069,7 @@ TEST_F(ResolverTest, UnaryOp_Complement) {
} }
TEST_F(ResolverTest, UnaryOp_Negation) { TEST_F(ResolverTest, UnaryOp_Negation) {
GlobalVar("ident", ty.u32(), ast::StorageClass::kPrivate); GlobalVar("ident", ty.u32(), ast::AddressSpace::kPrivate);
auto* der = auto* der =
create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation, Expr(Source{{12, 34}}, "ident")); create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation, Expr(Source{{12, 34}}, "ident"));
WrapInFunction(der); WrapInFunction(der);
@ -2214,15 +2214,15 @@ TEST_F(ResolverTest, TextureSampler_TextureDimensions) {
TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) { TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) {
auto* f0 = Func("f0", utils::Empty, ty.void_(), utils::Empty); auto* f0 = Func("f0", utils::Empty, ty.void_(), utils::Empty);
auto* v0 = GlobalVar("v0", ty.i32(), ast::StorageClass::kPrivate); auto* v0 = GlobalVar("v0", ty.i32(), ast::AddressSpace::kPrivate);
auto* a0 = Alias("a0", ty.i32()); auto* a0 = Alias("a0", ty.i32());
auto* s0 = Structure("s0", utils::Vector{Member("m", ty.i32())}); auto* s0 = Structure("s0", utils::Vector{Member("m", ty.i32())});
auto* f1 = Func("f1", utils::Empty, ty.void_(), utils::Empty); auto* f1 = Func("f1", utils::Empty, ty.void_(), utils::Empty);
auto* v1 = GlobalVar("v1", ty.i32(), ast::StorageClass::kPrivate); auto* v1 = GlobalVar("v1", ty.i32(), ast::AddressSpace::kPrivate);
auto* a1 = Alias("a1", ty.i32()); auto* a1 = Alias("a1", ty.i32());
auto* s1 = Structure("s1", utils::Vector{Member("m", ty.i32())}); auto* s1 = Structure("s1", utils::Vector{Member("m", ty.i32())});
auto* f2 = Func("f2", utils::Empty, ty.void_(), utils::Empty); auto* f2 = Func("f2", utils::Empty, ty.void_(), utils::Empty);
auto* v2 = GlobalVar("v2", ty.i32(), ast::StorageClass::kPrivate); auto* v2 = GlobalVar("v2", ty.i32(), ast::AddressSpace::kPrivate);
auto* a2 = Alias("a2", ty.i32()); auto* a2 = Alias("a2", ty.i32());
auto* s2 = Structure("s2", utils::Vector{Member("m", ty.i32())}); auto* s2 = Structure("s2", utils::Vector{Member("m", ty.i32())});

View File

@ -604,13 +604,13 @@ struct DataType<ptr<T>> {
/// @param b the ProgramBuilder /// @param b the ProgramBuilder
/// @return a new AST alias type /// @return a new AST alias type
static inline const ast::Type* AST(ProgramBuilder& b) { static inline const ast::Type* AST(ProgramBuilder& b) {
return b.create<ast::Pointer>(DataType<T>::AST(b), ast::StorageClass::kPrivate, return b.create<ast::Pointer>(DataType<T>::AST(b), ast::AddressSpace::kPrivate,
ast::Access::kReadWrite); ast::Access::kReadWrite);
} }
/// @param b the ProgramBuilder /// @param b the ProgramBuilder
/// @return the semantic aliased type /// @return the semantic aliased type
static inline const sem::Type* Sem(ProgramBuilder& b) { static inline const sem::Type* Sem(ProgramBuilder& b) {
return b.create<sem::Pointer>(DataType<T>::Sem(b), ast::StorageClass::kPrivate, return b.create<sem::Pointer>(DataType<T>::Sem(b), ast::AddressSpace::kPrivate,
ast::Access::kReadWrite); ast::Access::kReadWrite);
} }
@ -618,7 +618,7 @@ struct DataType<ptr<T>> {
/// @return a new AST expression of the pointer type /// @return a new AST expression of the pointer type
static inline const ast::Expression* Expr(ProgramBuilder& b, ScalarArgs /*unused*/) { static inline const ast::Expression* Expr(ProgramBuilder& b, ScalarArgs /*unused*/) {
auto sym = b.Symbols().New("global_for_ptr"); auto sym = b.Symbols().New("global_for_ptr");
b.GlobalVar(sym, DataType<T>::AST(b), ast::StorageClass::kPrivate); b.GlobalVar(sym, DataType<T>::AST(b), ast::AddressSpace::kPrivate);
return b.AddressOf(sym); return b.AddressOf(sym);
} }

View File

@ -30,7 +30,7 @@ struct SideEffectsTest : ResolverTest {
template <typename T> template <typename T>
void MakeSideEffectFunc(const char* name) { void MakeSideEffectFunc(const char* name) {
auto global = Sym(); auto global = Sym();
GlobalVar(global, ty.Of<T>(), ast::StorageClass::kPrivate); GlobalVar(global, ty.Of<T>(), ast::AddressSpace::kPrivate);
auto local = Sym(); auto local = Sym();
Func(name, utils::Empty, ty.Of<T>(), Func(name, utils::Empty, ty.Of<T>(),
utils::Vector{ utils::Vector{
@ -43,7 +43,7 @@ struct SideEffectsTest : ResolverTest {
template <typename MAKE_TYPE_FUNC> template <typename MAKE_TYPE_FUNC>
void MakeSideEffectFunc(const char* name, MAKE_TYPE_FUNC make_type) { void MakeSideEffectFunc(const char* name, MAKE_TYPE_FUNC make_type) {
auto global = Sym(); auto global = Sym();
GlobalVar(global, make_type(), ast::StorageClass::kPrivate); GlobalVar(global, make_type(), ast::AddressSpace::kPrivate);
auto local = Sym(); auto local = Sym();
Func(name, utils::Empty, make_type(), Func(name, utils::Empty, make_type(),
utils::Vector{ utils::Vector{
@ -88,7 +88,7 @@ TEST_F(SideEffectsTest, VariableUser) {
} }
TEST_F(SideEffectsTest, Call_Builtin_NoSE) { TEST_F(SideEffectsTest, Call_Builtin_NoSE) {
GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate);
auto* expr = Call("dpdx", "a"); auto* expr = Call("dpdx", "a");
Func("f", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)}, Func("f", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)},
utils::Vector{create<ast::StageAttribute>(ast::PipelineStage::kFragment)}); utils::Vector{create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
@ -114,7 +114,7 @@ TEST_F(SideEffectsTest, Call_Builtin_NoSE_WithSEArg) {
} }
TEST_F(SideEffectsTest, Call_Builtin_SE) { TEST_F(SideEffectsTest, Call_Builtin_SE) {
GlobalVar("a", ty.atomic(ty.i32()), ast::StorageClass::kWorkgroup); GlobalVar("a", ty.atomic(ty.i32()), ast::AddressSpace::kWorkgroup);
auto* expr = Call("atomicAdd", AddressOf("a"), 1_i); auto* expr = Call("atomicAdd", AddressOf("a"), 1_i);
WrapInFunction(expr); WrapInFunction(expr);
@ -163,20 +163,20 @@ TEST_P(SideEffectsBuiltinTest, Test) {
auto& c = GetParam(); auto& c = GetParam();
uint32_t next_binding = 0; uint32_t next_binding = 0;
GlobalVar("f", ty.f32(), ast::StorageClass::kPrivate); GlobalVar("f", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("i", ty.i32(), ast::StorageClass::kPrivate); GlobalVar("i", ty.i32(), ast::AddressSpace::kPrivate);
GlobalVar("u", ty.u32(), ast::StorageClass::kPrivate); GlobalVar("u", ty.u32(), ast::AddressSpace::kPrivate);
GlobalVar("b", ty.bool_(), ast::StorageClass::kPrivate); GlobalVar("b", ty.bool_(), ast::AddressSpace::kPrivate);
GlobalVar("vf", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("vf", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
GlobalVar("vf2", ty.vec2<f32>(), ast::StorageClass::kPrivate); GlobalVar("vf2", ty.vec2<f32>(), ast::AddressSpace::kPrivate);
GlobalVar("vi2", ty.vec2<i32>(), ast::StorageClass::kPrivate); GlobalVar("vi2", ty.vec2<i32>(), ast::AddressSpace::kPrivate);
GlobalVar("vf4", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("vf4", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
GlobalVar("vb", ty.vec3<bool>(), ast::StorageClass::kPrivate); GlobalVar("vb", ty.vec3<bool>(), ast::AddressSpace::kPrivate);
GlobalVar("m", ty.mat3x3<f32>(), ast::StorageClass::kPrivate); GlobalVar("m", ty.mat3x3<f32>(), ast::AddressSpace::kPrivate);
GlobalVar("arr", ty.array<f32, 10>(), ast::StorageClass::kPrivate); GlobalVar("arr", ty.array<f32, 10>(), ast::AddressSpace::kPrivate);
GlobalVar("storage_arr", ty.array<f32>(), ast::StorageClass::kStorage, Group(0_a), GlobalVar("storage_arr", ty.array<f32>(), ast::AddressSpace::kStorage, Group(0_a),
Binding(AInt(next_binding++))); Binding(AInt(next_binding++)));
GlobalVar("a", ty.atomic(ty.i32()), ast::StorageClass::kStorage, ast::Access::kReadWrite, GlobalVar("a", ty.atomic(ty.i32()), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Group(0_a), Binding(AInt(next_binding++))); Group(0_a), Binding(AInt(next_binding++)));
if (c.pipeline_stage != ast::PipelineStage::kCompute) { if (c.pipeline_stage != ast::PipelineStage::kCompute) {
GlobalVar("t2d", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), Group(0_a), GlobalVar("t2d", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), Group(0_a),

View File

@ -26,7 +26,7 @@ namespace {
class ResolverSourceVariableTest : public ResolverTest {}; class ResolverSourceVariableTest : public ResolverTest {};
TEST_F(ResolverSourceVariableTest, GlobalPrivateVar) { TEST_F(ResolverSourceVariableTest, GlobalPrivateVar) {
auto* a = GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate);
auto* expr = Expr(a); auto* expr = Expr(a);
WrapInFunction(expr); WrapInFunction(expr);
@ -37,7 +37,7 @@ TEST_F(ResolverSourceVariableTest, GlobalPrivateVar) {
} }
TEST_F(ResolverSourceVariableTest, GlobalWorkgroupVar) { TEST_F(ResolverSourceVariableTest, GlobalWorkgroupVar) {
auto* a = GlobalVar("a", ty.f32(), ast::StorageClass::kWorkgroup); auto* a = GlobalVar("a", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* expr = Expr(a); auto* expr = Expr(a);
WrapInFunction(expr); WrapInFunction(expr);
@ -48,7 +48,7 @@ TEST_F(ResolverSourceVariableTest, GlobalWorkgroupVar) {
} }
TEST_F(ResolverSourceVariableTest, GlobalStorageVar) { TEST_F(ResolverSourceVariableTest, GlobalStorageVar) {
auto* a = GlobalVar("a", ty.f32(), ast::StorageClass::kStorage, Group(0_a), Binding(0_a)); auto* a = GlobalVar("a", ty.f32(), ast::AddressSpace::kStorage, Group(0_a), Binding(0_a));
auto* expr = Expr(a); auto* expr = Expr(a);
WrapInFunction(expr); WrapInFunction(expr);
@ -59,7 +59,7 @@ TEST_F(ResolverSourceVariableTest, GlobalStorageVar) {
} }
TEST_F(ResolverSourceVariableTest, GlobalUniformVar) { TEST_F(ResolverSourceVariableTest, GlobalUniformVar) {
auto* a = GlobalVar("a", ty.f32(), ast::StorageClass::kUniform, Group(0_a), Binding(0_a)); auto* a = GlobalVar("a", ty.f32(), ast::AddressSpace::kUniform, Group(0_a), Binding(0_a));
auto* expr = Expr(a); auto* expr = Expr(a);
WrapInFunction(expr); WrapInFunction(expr);
@ -71,7 +71,7 @@ TEST_F(ResolverSourceVariableTest, GlobalUniformVar) {
TEST_F(ResolverSourceVariableTest, GlobalTextureVar) { TEST_F(ResolverSourceVariableTest, GlobalTextureVar) {
auto* a = GlobalVar("a", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), auto* a = GlobalVar("a", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()),
ast::StorageClass::kNone, Group(0_a), Binding(0_a)); ast::AddressSpace::kNone, Group(0_a), Binding(0_a));
auto* expr = Expr(a); auto* expr = Expr(a);
WrapInFunction(Call("textureDimensions", expr)); WrapInFunction(Call("textureDimensions", expr));
@ -141,7 +141,7 @@ TEST_F(ResolverSourceVariableTest, PointerParameter) {
// { // {
// let b = a; // let b = a;
// } // }
auto* param = Param("a", ty.pointer(ty.f32(), ast::StorageClass::kFunction)); auto* param = Param("a", ty.pointer(ty.f32(), ast::AddressSpace::kFunction));
auto* expr_param = Expr(param); auto* expr_param = Expr(param);
auto* let = Let("b", expr_param); auto* let = Let("b", expr_param);
auto* expr_let = Expr("b"); auto* expr_let = Expr("b");
@ -198,7 +198,7 @@ TEST_F(ResolverSourceVariableTest, ThroughIndexAccessor) {
// { // {
// a[2i] // a[2i]
// } // }
auto* a = GlobalVar("a", ty.array(ty.f32(), 4_u), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.array(ty.f32(), 4_u), ast::AddressSpace::kPrivate);
auto* expr = IndexAccessor(a, 2_i); auto* expr = IndexAccessor(a, 2_i);
WrapInFunction(expr); WrapInFunction(expr);
@ -215,7 +215,7 @@ TEST_F(ResolverSourceVariableTest, ThroughMemberAccessor) {
// a.f // a.f
// } // }
auto* S = Structure("S", utils::Vector{Member("f", ty.f32())}); auto* S = Structure("S", utils::Vector{Member("f", ty.f32())});
auto* a = GlobalVar("a", ty.Of(S), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.Of(S), ast::AddressSpace::kPrivate);
auto* expr = MemberAccessor(a, "f"); auto* expr = MemberAccessor(a, "f");
WrapInFunction(expr); WrapInFunction(expr);
@ -231,7 +231,7 @@ TEST_F(ResolverSourceVariableTest, ThroughPointers) {
// let a_ptr1 = &*&a; // let a_ptr1 = &*&a;
// let a_ptr2 = &*a_ptr1; // let a_ptr2 = &*a_ptr1;
// } // }
auto* a = GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate); auto* a = GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate);
auto* address_of_1 = AddressOf(a); auto* address_of_1 = AddressOf(a);
auto* deref_1 = Deref(address_of_1); auto* deref_1 = Deref(address_of_1);
auto* address_of_2 = AddressOf(deref_1); auto* address_of_2 = AddressOf(deref_1);

View File

@ -86,7 +86,7 @@ TEST_F(ResolverStaticAssertTest, Local_Const_Fail) {
} }
TEST_F(ResolverStaticAssertTest, Local_NonConst) { TEST_F(ResolverStaticAssertTest, Local_NonConst) {
GlobalVar("V", ty.bool_(), Expr(true), ast::StorageClass::kPrivate); GlobalVar("V", ty.bool_(), Expr(true), ast::AddressSpace::kPrivate);
WrapInFunction(StaticAssert(Expr(Source{{12, 34}}, "V"))); WrapInFunction(StaticAssert(Expr(Source{{12, 34}}, "V")));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),

View File

@ -25,19 +25,19 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::resolver { namespace tint::resolver {
namespace { namespace {
using ResolverStorageClassUseTest = ResolverTest; using ResolverAddressSpaceUseTest = ResolverTest;
TEST_F(ResolverStorageClassUseTest, UnreachableStruct) { TEST_F(ResolverAddressSpaceUseTest, UnreachableStruct) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->StorageClassUsage().empty()); EXPECT_TRUE(sem->AddressSpaceUsage().empty());
} }
TEST_F(ResolverStorageClassUseTest, StructReachableFromParameter) { TEST_F(ResolverAddressSpaceUseTest, StructReachableFromParameter) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
Func("f", utils::Vector{Param("param", ty.Of(s))}, ty.void_(), utils::Empty, utils::Empty); Func("f", utils::Vector{Param("param", ty.Of(s))}, ty.void_(), utils::Empty, utils::Empty);
@ -46,10 +46,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromParameter) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kNone)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kNone));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableFromReturnType) { TEST_F(ResolverAddressSpaceUseTest, StructReachableFromReturnType) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
Func("f", utils::Empty, ty.Of(s), utils::Vector{Return(Construct(ty.Of(s)))}, utils::Empty); Func("f", utils::Empty, ty.Of(s), utils::Vector{Return(Construct(ty.Of(s)))}, utils::Empty);
@ -58,58 +58,58 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromReturnType) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kNone)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kNone));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableFromGlobal) { TEST_F(ResolverAddressSpaceUseTest, StructReachableFromGlobal) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
GlobalVar("g", ty.Of(s), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(s), ast::AddressSpace::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kPrivate)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kPrivate));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalAlias) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalAlias) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = Alias("A", ty.Of(s)); auto* a = Alias("A", ty.Of(s));
GlobalVar("g", ty.Of(a), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(a), ast::AddressSpace::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kPrivate)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kPrivate));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalStruct) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalStruct) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* o = Structure("O", utils::Vector{Member("a", ty.Of(s))}); auto* o = Structure("O", utils::Vector{Member("a", ty.Of(s))});
GlobalVar("g", ty.Of(o), ast::StorageClass::kPrivate); GlobalVar("g", ty.Of(o), ast::AddressSpace::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kPrivate)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kPrivate));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalArray) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaGlobalArray) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
GlobalVar("g", a, ast::StorageClass::kPrivate); GlobalVar("g", a, ast::AddressSpace::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kPrivate)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kPrivate));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) { TEST_F(ResolverAddressSpaceUseTest, StructReachableFromLocal) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
WrapInFunction(Var("g", ty.Of(s))); WrapInFunction(Var("g", ty.Of(s)));
@ -118,10 +118,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kFunction)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kFunction));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalAlias) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = Alias("A", ty.Of(s)); auto* a = Alias("A", ty.Of(s));
WrapInFunction(Var("g", ty.Of(a))); WrapInFunction(Var("g", ty.Of(a)));
@ -130,10 +130,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kFunction)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kFunction));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalStruct) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* o = Structure("O", utils::Vector{Member("a", ty.Of(s))}); auto* o = Structure("O", utils::Vector{Member("a", ty.Of(s))});
WrapInFunction(Var("g", ty.Of(o))); WrapInFunction(Var("g", ty.Of(o)));
@ -142,10 +142,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kFunction)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kFunction));
} }
TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) { TEST_F(ResolverAddressSpaceUseTest, StructReachableViaLocalArray) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
auto* a = ty.array(ty.Of(s), 3_u); auto* a = ty.array(ty.Of(s), 3_u);
WrapInFunction(Var("g", a)); WrapInFunction(Var("g", a));
@ -154,13 +154,13 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), UnorderedElementsAre(ast::StorageClass::kFunction)); EXPECT_THAT(sem->AddressSpaceUsage(), UnorderedElementsAre(ast::AddressSpace::kFunction));
} }
TEST_F(ResolverStorageClassUseTest, StructMultipleStorageClassUses) { TEST_F(ResolverAddressSpaceUseTest, StructMultipleAddressSpaceUses) {
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())}); auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
GlobalVar("x", ty.Of(s), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("x", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
GlobalVar("y", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, Binding(1_a), GlobalVar("y", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(1_a),
Group(0_a)); Group(0_a));
WrapInFunction(Var("g", ty.Of(s))); WrapInFunction(Var("g", ty.Of(s)));
@ -168,9 +168,9 @@ TEST_F(ResolverStorageClassUseTest, StructMultipleStorageClassUses) {
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(), EXPECT_THAT(sem->AddressSpaceUsage(),
UnorderedElementsAre(ast::StorageClass::kUniform, ast::StorageClass::kStorage, UnorderedElementsAre(ast::AddressSpace::kUniform, ast::AddressSpace::kStorage,
ast::StorageClass::kFunction)); ast::AddressSpace::kFunction));
} }
} // namespace } // namespace

View File

@ -69,10 +69,10 @@ TEST_F(ResolverTypeConstructorValidationTest, InferTypeTest_Simple) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(a_ident)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(a_ident)->Is<sem::Reference>());
EXPECT_TRUE(TypeOf(a_ident)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(a_ident)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
EXPECT_EQ(TypeOf(a_ident)->As<sem::Reference>()->StorageClass(), ast::StorageClass::kFunction); EXPECT_EQ(TypeOf(a_ident)->As<sem::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
ASSERT_TRUE(TypeOf(b_ident)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(b_ident)->Is<sem::Reference>());
EXPECT_TRUE(TypeOf(b_ident)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(b_ident)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
EXPECT_EQ(TypeOf(b_ident)->As<sem::Reference>()->StorageClass(), ast::StorageClass::kFunction); EXPECT_EQ(TypeOf(b_ident)->As<sem::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
} }
using InferTypeTest_FromConstructorExpression = ResolverTestWithParam<Params>; using InferTypeTest_FromConstructorExpression = ResolverTestWithParam<Params>;
@ -96,7 +96,7 @@ TEST_P(InferTypeTest_FromConstructorExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
ast::StorageClass::kFunction, ast::Access::kReadWrite); ast::AddressSpace::kFunction, ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }
@ -150,7 +150,7 @@ TEST_P(InferTypeTest_FromArithmeticExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
ast::StorageClass::kFunction, ast::Access::kReadWrite); ast::AddressSpace::kFunction, ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }
@ -198,7 +198,7 @@ TEST_P(InferTypeTest_FromCallExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident); auto* got = TypeOf(a_ident);
auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this), auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
ast::StorageClass::kFunction, ast::Access::kReadWrite); ast::AddressSpace::kFunction, ast::Access::kReadWrite);
ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n" ASSERT_EQ(got, expected) << "got: " << FriendlyName(got) << "\n"
<< "expected: " << FriendlyName(expected) << "\n"; << "expected: " << FriendlyName(expected) << "\n";
} }
@ -1968,7 +1968,7 @@ TEST_F(ResolverTypeConstructorValidationTest, NestedVectorConstructors_Success)
TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) { TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) {
auto* alias = Alias("UnsignedInt", ty.u32()); auto* alias = Alias("UnsignedInt", ty.u32());
GlobalVar("uint_var", ty.Of(alias), ast::StorageClass::kPrivate); GlobalVar("uint_var", ty.Of(alias), ast::AddressSpace::kPrivate);
auto* tc = vec2<f32>(Source{{12, 34}}, "uint_var"); auto* tc = vec2<f32>(Source{{12, 34}}, "uint_var");
WrapInFunction(tc); WrapInFunction(tc);
@ -1980,8 +1980,8 @@ TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) {
TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Success) { TEST_F(ResolverTypeConstructorValidationTest, 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>());
GlobalVar("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate); GlobalVar("my_f32", ty.Of(f32_alias), ast::AddressSpace::kPrivate);
GlobalVar("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate); GlobalVar("my_vec2", ty.Of(vec2_alias), ast::AddressSpace::kPrivate);
auto* tc = vec3<f32>("my_vec2", "my_f32"); auto* tc = vec3<f32>("my_vec2", "my_f32");
WrapInFunction(tc); WrapInFunction(tc);

View File

@ -80,14 +80,14 @@ TEST_F(ResolverTypeValidationTest, GlobalOverrideNoConstructor_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, GlobalVariableWithStorageClass_Pass) { TEST_F(ResolverTypeValidationTest, GlobalVariableWithAddressSpace_Pass) {
// var<private> global_var: f32; // var<private> global_var: f32;
GlobalVar(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kPrivate); GlobalVar(Source{{12, 34}}, "global_var", ty.f32(), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, GlobalConstNoStorageClass_Pass) { TEST_F(ResolverTypeValidationTest, GlobalConstNoAddressSpace_Pass) {
// const global_const: f32 = f32(); // const global_const: f32 = f32();
GlobalConst(Source{{12, 34}}, "global_const", ty.f32(), Construct(ty.f32())); GlobalConst(Source{{12, 34}}, "global_const", ty.f32(), Construct(ty.f32()));
@ -98,9 +98,9 @@ TEST_F(ResolverTypeValidationTest, GlobalVariableUnique_Pass) {
// var global_var0 : f32 = 0.1; // var global_var0 : f32 = 0.1;
// var global_var1 : i32 = 0; // var global_var1 : i32 = 0;
GlobalVar("global_var0", ty.f32(), ast::StorageClass::kPrivate, Expr(0.1_f)); GlobalVar("global_var0", ty.f32(), ast::AddressSpace::kPrivate, Expr(0.1_f));
GlobalVar(Source{{12, 34}}, "global_var1", ty.f32(), ast::StorageClass::kPrivate, Expr(1_f)); GlobalVar(Source{{12, 34}}, "global_var1", ty.f32(), ast::AddressSpace::kPrivate, Expr(1_f));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -116,7 +116,7 @@ TEST_F(ResolverTypeValidationTest, GlobalVariableFunctionVariableNotUnique_Pass)
Decl(Var("a", ty.f32(), Expr(2_f))), Decl(Var("a", ty.f32(), Expr(2_f))),
}); });
GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1_f)); GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate, Expr(2.1_f));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -180,19 +180,19 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierDifferentFunctions_Pass)
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Pass) { TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Pass) {
// var<private> a : array<f32, 4>; // var<private> a : array<f32, 4>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_a)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_a)), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Pass) { TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Pass) {
// var<private> a : array<f32, 4u>; // var<private> a : array<f32, 4u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_u)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_u)), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Pass) { TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Pass) {
// var<private> a : array<f32, 4i>; // var<private> a : array<f32, 4i>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_i)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_i)), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -200,7 +200,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConst_Pass) {
// const size = 4u; // const size = 4u;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(4_u)); GlobalConst("size", Expr(4_u));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -208,34 +208,34 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConst_Pass) {
// const size = 4i; // const size = 4i;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(4_i)); GlobalConst("size", Expr(4_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Zero) { TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Zero) {
// var<private> a : array<f32, 0>; // var<private> a : array<f32, 0>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_a)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_a)), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
} }
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Zero) { TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Zero) {
// var<private> a : array<f32, 0u>; // var<private> a : array<f32, 0u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_u)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_u)), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
} }
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Zero) { TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Zero) {
// var<private> a : array<f32, 0i>; // var<private> a : array<f32, 0i>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_i)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_i)), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
} }
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Negative) { TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Negative) {
// var<private> a : array<f32, -10i>; // var<private> a : array<f32, -10i>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, -10_i)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, -10_i)), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (-10) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (-10) must be greater than 0");
} }
@ -244,7 +244,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConst_Zero) {
// const size = 0u; // const size = 0u;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(0_u)); GlobalConst("size", Expr(0_u));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
} }
@ -253,7 +253,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConst_Zero) {
// const size = 0i; // const size = 0i;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(0_i)); GlobalConst("size", Expr(0_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
} }
@ -262,14 +262,14 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConst_Negative) {
// const size = -10i; // const size = -10i;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(-10_i)); GlobalConst("size", Expr(-10_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size (-10) must be greater than 0"); EXPECT_EQ(r()->error(), "12:34 error: array size (-10) must be greater than 0");
} }
TEST_F(ResolverTypeValidationTest, ArraySize_FloatLiteral) { TEST_F(ResolverTypeValidationTest, ArraySize_FloatLiteral) {
// var<private> a : array<f32, 10.0>; // var<private> a : array<f32, 10.0>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 10_f)), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 10_f)), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size must evaluate to a constant integer expression, but is type " "12:34 error: array size must evaluate to a constant integer expression, but is type "
@ -279,7 +279,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_FloatLiteral) {
TEST_F(ResolverTypeValidationTest, ArraySize_IVecLiteral) { TEST_F(ResolverTypeValidationTest, ArraySize_IVecLiteral) {
// var<private> a : array<f32, vec2<i32>(10, 10)>; // var<private> a : array<f32, vec2<i32>(10, 10)>;
GlobalVar("a", ty.array(ty.f32(), Construct(Source{{12, 34}}, ty.vec2<i32>(), 10_i, 10_i)), GlobalVar("a", ty.array(ty.f32(), Construct(Source{{12, 34}}, ty.vec2<i32>(), 10_i, 10_i)),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size must evaluate to a constant integer expression, but is type " "12:34 error: array size must evaluate to a constant integer expression, but is type "
@ -290,7 +290,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_FloatConst) {
// const size = 10.0; // const size = 10.0;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Expr(10_f)); GlobalConst("size", Expr(10_f));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size must evaluate to a constant integer expression, but is type " "12:34 error: array size must evaluate to a constant integer expression, but is type "
@ -301,7 +301,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_IVecConst) {
// const size = vec2<i32>(100, 100); // const size = vec2<i32>(100, 100);
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", Construct(ty.vec2<i32>(), 100_i, 100_i)); GlobalConst("size", Construct(ty.vec2<i32>(), 100_i, 100_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size must evaluate to a constant integer expression, but is type " "12:34 error: array size must evaluate to a constant integer expression, but is type "
@ -311,7 +311,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_IVecConst) {
TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ImplicitStride) { TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ImplicitStride) {
// var<private> a : array<f32, 0x40000000u>; // var<private> a : array<f32, 0x40000000u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x40000000_u)), GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x40000000_u)),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size (0x100000000) must not exceed 0xffffffff bytes"); "12:34 error: array size (0x100000000) must not exceed 0xffffffff bytes");
@ -320,7 +320,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ImplicitStride) {
TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) { TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) {
// var<private> a : @stride(8) array<f32, 0x20000000u>; // var<private> a : @stride(8) array<f32, 0x20000000u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x20000000_u), 8), GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x20000000_u), 8),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size (0x100000000) must not exceed 0xffffffff bytes"); "12:34 error: array size (0x100000000) must not exceed 0xffffffff bytes");
@ -330,7 +330,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_PrivateVar) {
// override size = 10i; // override size = 10i;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("a", ty.array(Source{{12, 34}}, ty.f32(), "size"), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(Source{{12, 34}}, ty.f32(), "size"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array with an 'override' element count can only be used as the store " "12:34 error: array with an 'override' element count can only be used as the store "
@ -342,7 +342,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_ComplexExpr) {
// var<workgroup> a : array<f32, size + 1>; // var<workgroup> a : array<f32, size + 1>;
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("a", ty.array(ty.f32(), Add(Source{{12, 34}}, "size", 1_i)), GlobalVar("a", ty.array(ty.f32(), Add(Source{{12, 34}}, "size", 1_i)),
ast::StorageClass::kWorkgroup); ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array size must evaluate to a constant integer expression or override " "12:34 error: array size must evaluate to a constant integer expression or override "
@ -354,7 +354,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_InArray) {
// var<workgroup> a : array<array<f32, size>, 4>; // var<workgroup> a : array<array<f32, size>, 4>;
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("a", ty.array(ty.array(Source{{12, 34}}, ty.f32(), "size"), 4_a), GlobalVar("a", ty.array(ty.array(Source{{12, 34}}, ty.f32(), "size"), 4_a),
ast::StorageClass::kWorkgroup); ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: array with an 'override' element count can only be used as the store " "12:34 error: array with an 'override' element count can only be used as the store "
@ -413,7 +413,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_FunctionVar_Implicit) {
// var a = w; // var a = w;
// } // }
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("w", ty.array(ty.f32(), "size"), ast::StorageClass::kWorkgroup); GlobalVar("w", ty.array(ty.f32(), "size"), ast::AddressSpace::kWorkgroup);
Func("f", utils::Empty, ty.void_(), Func("f", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
Decl(Var("a", Expr(Source{{12, 34}}, "w"))), Decl(Var("a", Expr(Source{{12, 34}}, "w"))),
@ -431,7 +431,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_FunctionLet_Implicit) {
// let a = w; // let a = w;
// } // }
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("w", ty.array(ty.f32(), "size"), ast::StorageClass::kWorkgroup); GlobalVar("w", ty.array(ty.f32(), "size"), ast::AddressSpace::kWorkgroup);
Func("f", utils::Empty, ty.void_(), Func("f", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
Decl(Let("a", Expr(Source{{12, 34}}, "w"))), Decl(Let("a", Expr(Source{{12, 34}}, "w"))),
@ -468,15 +468,15 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Workgroup_Overridable) {
// var<workgroup> a : array<f32, size>; // var<workgroup> a : array<f32, size>;
Override("size", Expr(10_i)); Override("size", Expr(10_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")),
ast::StorageClass::kWorkgroup); ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, ArraySize_ModuleVar) { TEST_F(ResolverTypeValidationTest, ArraySize_ModuleVar) {
// var<private> size : i32 = 10i; // var<private> size : i32 = 10i;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalVar("size", ty.i32(), Expr(10_i), ast::StorageClass::kPrivate); GlobalVar("size", ty.i32(), Expr(10_i), ast::AddressSpace::kPrivate);
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::StorageClass::kPrivate); GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: var 'size' cannot be referenced at module-scope R"(12:34 error: var 'size' cannot be referenced at module-scope
@ -531,7 +531,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
12:34 note: while instantiating 'var' a)"); 12:34 note: while instantiating 'var' a)");
} }
@ -631,7 +631,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInStructInArray) {
Structure("Foo", utils::Vector{Member("rt", ty.array<f32>())}); Structure("Foo", utils::Vector{Member("rt", ty.array<f32>())});
GlobalVar("v", ty.array(ty.type_name(Source{{12, 34}}, "Foo"), 4_u), GlobalVar("v", ty.array(ty.type_name(Source{{12, 34}}, "Foo"), 4_u),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -676,12 +676,12 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) {
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) { TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) {
GlobalVar(Source{{56, 78}}, "g", ty.array<i32>(), ast::StorageClass::kPrivate); GlobalVar(Source{{56, 78}}, "g", ty.array<i32>(), ast::AddressSpace::kPrivate);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class R"(56:78 error: runtime-sized arrays can only be used in the <storage> address space
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
@ -692,7 +692,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class R"(56:78 error: runtime-sized arrays can only be used in the <storage> address space
56:78 note: while instantiating 'var' g)"); 56:78 note: while instantiating 'var' g)");
} }
@ -717,7 +717,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
12:34 note: while instantiating parameter a)"); 12:34 note: while instantiating parameter a)");
} }
@ -725,7 +725,7 @@ TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsParameter_Fail) {
// fn func(a : ptr<workgroup, array<u32>>) {} // fn func(a : ptr<workgroup, array<u32>>) {}
auto* param = auto* param =
Param(Source{{12, 34}}, "a", ty.pointer(ty.array<i32>(), ast::StorageClass::kWorkgroup)); Param(Source{{12, 34}}, "a", ty.pointer(ty.array<i32>(), ast::AddressSpace::kWorkgroup));
Func("func", utils::Vector{param}, ty.void_(), Func("func", utils::Vector{param}, ty.void_(),
utils::Vector{ utils::Vector{
@ -734,7 +734,7 @@ TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsParameter_Fail) {
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class R"(12:34 error: runtime-sized arrays can only be used in the <storage> address space
12:34 note: while instantiating parameter a)"); 12:34 note: while instantiating parameter a)");
} }
@ -774,7 +774,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) {
TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) { TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) {
auto* tex_ty = ty.sampled_texture(Source{{12, 34}}, ast::TextureDimension::k2d, ty.f32()); auto* tex_ty = ty.sampled_texture(Source{{12, 34}}, ast::TextureDimension::k2d, ty.f32());
GlobalVar("arr", ty.array(tex_ty, 4_i), ast::StorageClass::kPrivate); GlobalVar("arr", ty.array(tex_ty, 4_i), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -784,8 +784,8 @@ TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) {
TEST_F(ResolverTypeValidationTest, VariableAsType) { TEST_F(ResolverTypeValidationTest, VariableAsType) {
// var<private> a : i32; // var<private> a : i32;
// var<private> b : a; // var<private> b : a;
GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate); GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
GlobalVar("b", ty.type_name("a"), ast::StorageClass::kPrivate); GlobalVar("b", ty.type_name("a"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -797,7 +797,7 @@ TEST_F(ResolverTypeValidationTest, FunctionAsType) {
// fn f() {} // fn f() {}
// var<private> v : f; // var<private> v : f;
Func("f", utils::Empty, ty.void_(), {}); Func("f", utils::Empty, ty.void_(), {});
GlobalVar("v", ty.type_name("f"), ast::StorageClass::kPrivate); GlobalVar("v", ty.type_name("f"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -807,7 +807,7 @@ note: 'f' declared here)");
TEST_F(ResolverTypeValidationTest, BuiltinAsType) { TEST_F(ResolverTypeValidationTest, BuiltinAsType) {
// var<private> v : max; // var<private> v : max;
GlobalVar("v", ty.type_name("max"), ast::StorageClass::kPrivate); GlobalVar("v", ty.type_name("max"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "error: cannot use builtin 'max' as type"); EXPECT_EQ(r()->error(), "error: cannot use builtin 'max' as type");
@ -818,14 +818,14 @@ TEST_F(ResolverTypeValidationTest, F16TypeUsedWithExtension) {
// var<private> v : f16; // var<private> v : f16;
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("v", ty.f16(), ast::StorageClass::kPrivate); GlobalVar("v", ty.f16(), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeValidationTest, F16TypeUsedWithoutExtension) { TEST_F(ResolverTypeValidationTest, F16TypeUsedWithoutExtension) {
// var<private> v : f16; // var<private> v : f16;
GlobalVar("v", ty.f16(), ast::StorageClass::kPrivate); GlobalVar("v", ty.f16(), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "error: f16 used without 'f16' extension enabled"); EXPECT_EQ(r()->error(), "error: f16 used without 'f16' extension enabled");
@ -1179,7 +1179,7 @@ TEST_P(ValidMatrixTypes, Okay) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("a", ty.mat(params.elem_ty(*this), params.columns, params.rows), GlobalVar("a", ty.mat(params.elem_ty(*this), params.columns, params.rows),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@ -1217,7 +1217,7 @@ TEST_P(InvalidMatrixElementTypes, InvalidElementType) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("a", ty.mat(Source{{12, 34}}, params.elem_ty(*this), params.columns, params.rows), GlobalVar("a", ty.mat(Source{{12, 34}}, params.elem_ty(*this), params.columns, params.rows),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: matrix element type must be 'f32' or 'f16'"); EXPECT_EQ(r()->error(), "12:34 error: matrix element type must be 'f32' or 'f16'");
} }
@ -1258,7 +1258,7 @@ TEST_P(ValidVectorTypes, Okay) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("a", ty.vec(params.elem_ty(*this), params.width), ast::StorageClass::kPrivate); GlobalVar("a", ty.vec(params.elem_ty(*this), params.width), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@ -1292,7 +1292,7 @@ TEST_P(InvalidVectorElementTypes, InvalidElementType) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
GlobalVar("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width), GlobalVar("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width),
ast::StorageClass::kPrivate); ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' " "12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' "

View File

@ -1468,14 +1468,14 @@ class UniformityGraph {
[&](const ast::IdentifierExpression* ident) { [&](const ast::IdentifierExpression* ident) {
std::string var_type = ""; std::string var_type = "";
auto* var = sem_.Get<sem::VariableUser>(ident)->Variable(); auto* var = sem_.Get<sem::VariableUser>(ident)->Variable();
switch (var->StorageClass()) { switch (var->AddressSpace()) {
case ast::StorageClass::kStorage: case ast::AddressSpace::kStorage:
var_type = "read_write storage buffer "; var_type = "read_write storage buffer ";
break; break;
case ast::StorageClass::kWorkgroup: case ast::AddressSpace::kWorkgroup:
var_type = "workgroup storage variable "; var_type = "workgroup storage variable ";
break; break;
case ast::StorageClass::kPrivate: case ast::AddressSpace::kPrivate:
var_type = "module-scope private variable "; var_type = "module-scope private variable ";
break; break;
default: default:

View File

@ -5291,7 +5291,7 @@ TEST_F(UniformityAnalysisTest, MaximumNumberOfPointerParameters) {
foo_body.Push(b.Decl(b.Let("rhs", rhs_init))); foo_body.Push(b.Decl(b.Let("rhs", rhs_init)));
for (int i = 0; i < 255; i++) { for (int i = 0; i < 255; i++) {
params.Push( params.Push(
b.Param("p" + std::to_string(i), ty.pointer(ty.i32(), ast::StorageClass::kFunction))); b.Param("p" + std::to_string(i), ty.pointer(ty.i32(), ast::AddressSpace::kFunction)));
if (i > 0) { if (i > 0) {
foo_body.Push(b.Assign(b.Deref("p" + std::to_string(i)), "rhs")); foo_body.Push(b.Assign(b.Deref("p" + std::to_string(i)), "rhs"));
} }
@ -5310,7 +5310,7 @@ TEST_F(UniformityAnalysisTest, MaximumNumberOfPointerParameters) {
// workgroupBarrier(); // workgroupBarrier();
// } // }
// } // }
b.GlobalVar("non_uniform_global", ty.i32(), ast::StorageClass::kPrivate); b.GlobalVar("non_uniform_global", ty.i32(), ast::AddressSpace::kPrivate);
utils::Vector<const ast::Statement*, 8> main_body; utils::Vector<const ast::Statement*, 8> main_body;
utils::Vector<const ast::Expression*, 8> args; utils::Vector<const ast::Expression*, 8> args;
for (int i = 0; i < 255; i++) { for (int i = 0; i < 255; i++) {
@ -6519,7 +6519,7 @@ TEST_F(UniformityAnalysisTest, StressGraphTraversalDepth) {
// workgroupBarrier(); // workgroupBarrier();
// } // }
// } // }
b.GlobalVar("v0", ty.i32(), ast::StorageClass::kPrivate, b.Expr(0_i)); b.GlobalVar("v0", ty.i32(), ast::AddressSpace::kPrivate, b.Expr(0_i));
utils::Vector<const ast::Statement*, 8> foo_body; utils::Vector<const ast::Statement*, 8> foo_body;
std::string v_last = "v0"; std::string v_last = "v0";
for (int i = 1; i < 100000; i++) { for (int i = 1; i < 100000; i++) {

View File

@ -61,8 +61,8 @@ class FakeExpr final : public Castable<FakeExpr, ast::Expression> {
}; };
TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInVertexStage) { TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInVertexStage) {
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup); GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::AddressSpace::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("dst", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg")); auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Func(Source{{9, 10}}, "f0", utils::Empty, ty.vec4<f32>(), Func(Source{{9, 10}}, "f0", utils::Empty, ty.vec4<f32>(),
@ -93,8 +93,8 @@ TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInFragmentStage) {
// f1(); // f1();
//} //}
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup); GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::AddressSpace::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("dst", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg")); auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Func(Source{{5, 6}}, "f2", utils::Empty, ty.void_(), utils::Vector{stmt}); Func(Source{{5, 6}}, "f2", utils::Empty, ty.void_(), utils::Vector{stmt});
@ -226,7 +226,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
// return; // return;
// } // }
GlobalVar("global_var", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1_f)); GlobalVar("global_var", ty.f32(), ast::AddressSpace::kPrivate, Expr(2.1_f));
Func("my_func", utils::Empty, ty.void_(), Func("my_func", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -299,8 +299,8 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableDifferentScope_Fail) {
EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'a'"); EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'a'");
} }
TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) { TEST_F(ResolverValidationTest, AddressSpace_FunctionVariableWorkgroupClass) {
auto* var = Var("var", ty.i32(), ast::StorageClass::kWorkgroup); auto* var = Var("var", ty.i32(), ast::AddressSpace::kWorkgroup);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -310,11 +310,11 @@ TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: function-scope 'var' declaration must use 'function' storage class"); "error: function-scope 'var' declaration must use 'function' address space");
} }
TEST_F(ResolverValidationTest, StorageClass_FunctionVariableI32) { TEST_F(ResolverValidationTest, AddressSpace_FunctionVariableI32) {
auto* var = Var("s", ty.i32(), ast::StorageClass::kPrivate); auto* var = Var("s", ty.i32(), ast::AddressSpace::kPrivate);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -324,31 +324,31 @@ TEST_F(ResolverValidationTest, StorageClass_FunctionVariableI32) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error: function-scope 'var' declaration must use 'function' storage class"); "error: function-scope 'var' declaration must use 'function' address space");
} }
TEST_F(ResolverValidationTest, StorageClass_SamplerExplicitStorageClass) { TEST_F(ResolverValidationTest, AddressSpace_SamplerExplicitAddressSpace) {
auto* t = ty.sampler(ast::SamplerKind::kSampler); auto* t = ty.sampler(ast::SamplerKind::kSampler);
GlobalVar(Source{{12, 34}}, "var", t, ast::StorageClass::kHandle, Binding(0_a), Group(0_a)); GlobalVar(Source{{12, 34}}, "var", t, ast::AddressSpace::kHandle, Binding(0_a), Group(0_a));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: variables of type 'sampler' must not have a storage class)"); R"(12:34 error: variables of type 'sampler' must not have a address space)");
} }
TEST_F(ResolverValidationTest, StorageClass_TextureExplicitStorageClass) { TEST_F(ResolverValidationTest, AddressSpace_TextureExplicitAddressSpace) {
auto* t = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32()); auto* t = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32());
GlobalVar(Source{{12, 34}}, "var", t, ast::StorageClass::kHandle, Binding(0_a), Group(0_a)); GlobalVar(Source{{12, 34}}, "var", t, ast::AddressSpace::kHandle, Binding(0_a), Group(0_a));
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error: variables of type 'texture_1d<f32>' must not have a storage class)"); R"(12:34 error: variables of type 'texture_1d<f32>' must not have a address space)");
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) { TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
GlobalVar("my_vec", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "xyqz"); auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "xyqz");
@ -360,7 +360,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) { TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
GlobalVar("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "rgyw"); auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "rgyw");
@ -373,7 +373,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) { TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) {
GlobalVar("my_vec", ty.vec3<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec3<f32>(), ast::AddressSpace::kPrivate);
auto* ident = Expr(Source{{{3, 3}, {3, 8}}}, "zzzzz"); auto* ident = Expr(Source{{{3, 3}, {3, 8}}}, "zzzzz");
auto* mem = MemberAccessor("my_vec", ident); auto* mem = MemberAccessor("my_vec", ident);
@ -384,7 +384,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) {
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) { TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) {
GlobalVar("my_vec", ty.vec2<f32>(), ast::StorageClass::kPrivate); GlobalVar("my_vec", ty.vec2<f32>(), ast::AddressSpace::kPrivate);
auto* ident = Expr(Source{{3, 3}}, "z"); auto* ident = Expr(Source{{3, 3}}, "z");
auto* mem = MemberAccessor("my_vec", ident); auto* mem = MemberAccessor("my_vec", ident);
@ -417,7 +417,7 @@ TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) {
// let x: f32 = (*p).z; // let x: f32 = (*p).z;
// return x; // return x;
// } // }
auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction)); auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::AddressSpace::kFunction));
auto* star_p = Deref(p); auto* star_p = Deref(p);
auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z"); auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z");
auto* accessor_expr = MemberAccessor(star_p, z); auto* accessor_expr = MemberAccessor(star_p, z);
@ -435,7 +435,7 @@ TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncBadParent) {
// let x: f32 = *p.z; // let x: f32 = *p.z;
// return x; // return x;
// } // }
auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction)); auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::AddressSpace::kFunction));
auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z"); auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z");
auto* accessor_expr = MemberAccessor(p, z); auto* accessor_expr = MemberAccessor(p, z);
auto* star_p = Deref(accessor_expr); auto* star_p = Deref(accessor_expr);
@ -1312,8 +1312,8 @@ TEST_F(ResolverValidationTest, OffsetAndAlignAndSizeAttribute) {
TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) { TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
auto* vf = Var("vf", ty.f32()); auto* vf = Var("vf", ty.f32());
auto* c = auto* c =
Construct(Source{{12, 34}}, ty.pointer<i32>(ast::StorageClass::kFunction), ExprList(vf)); Construct(Source{{12, 34}}, ty.pointer<i32>(ast::AddressSpace::kFunction), ExprList(vf));
auto* ip = Let("ip", ty.pointer<i32>(ast::StorageClass::kFunction), c); auto* ip = Let("ip", ty.pointer<i32>(ast::AddressSpace::kFunction), c);
WrapInFunction(Decl(vf), Decl(ip)); WrapInFunction(Decl(vf), Decl(ip));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -322,7 +322,7 @@ bool Validator::Materialize(const sem::Type* to,
} }
bool Validator::VariableInitializer(const ast::Variable* v, bool Validator::VariableInitializer(const ast::Variable* v,
ast::StorageClass storage_class, ast::AddressSpace address_space,
const sem::Type* storage_ty, const sem::Type* storage_ty,
const sem::Expression* initializer) const { const sem::Expression* initializer) const {
auto* initializer_ty = initializer->Type(); auto* initializer_ty = initializer->Type();
@ -338,17 +338,17 @@ bool Validator::VariableInitializer(const ast::Variable* v,
} }
if (v->Is<ast::Var>()) { if (v->Is<ast::Var>()) {
switch (storage_class) { switch (address_space) {
case ast::StorageClass::kPrivate: case ast::AddressSpace::kPrivate:
case ast::StorageClass::kFunction: case ast::AddressSpace::kFunction:
break; // Allowed an initializer break; // Allowed an initializer
default: default:
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
// Optionally has an initializer expression, if the variable is in the // Optionally has an initializer expression, if the variable is in the
// private or function storage classes. // private or function address spacees.
AddError("var of storage class '" + utils::ToString(storage_class) + AddError("var of address space '" + utils::ToString(address_space) +
"' cannot have an initializer. var initializers are only " "' cannot have an initializer. var initializers are only "
"supported for the storage classes " "supported for the address spacees "
"'private' and 'function'", "'private' and 'function'",
v->source); v->source);
return false; return false;
@ -358,18 +358,19 @@ bool Validator::VariableInitializer(const ast::Variable* v,
return true; return true;
} }
bool Validator::StorageClassLayout(const sem::Type* store_ty, bool Validator::AddressSpaceLayout(const sem::Type* store_ty,
ast::StorageClass sc, ast::AddressSpace address_space,
Source source, Source source,
ValidTypeStorageLayouts& layouts) const { ValidTypeStorageLayouts& layouts) const {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class-layout-constraints // https://gpuweb.github.io/gpuweb/wgsl/#storage-class-layout-constraints
auto is_uniform_struct_or_array = [sc](const sem::Type* ty) { auto is_uniform_struct_or_array = [address_space](const sem::Type* ty) {
return sc == ast::StorageClass::kUniform && ty->IsAnyOf<sem::Array, sem::Struct>(); return address_space == ast::AddressSpace::kUniform &&
ty->IsAnyOf<sem::Array, sem::Struct>();
}; };
auto is_uniform_struct = [sc](const sem::Type* ty) { auto is_uniform_struct = [address_space](const sem::Type* ty) {
return sc == ast::StorageClass::kUniform && ty->Is<sem::Struct>(); return address_space == ast::AddressSpace::kUniform && ty->Is<sem::Struct>();
}; };
auto required_alignment_of = [&](const sem::Type* ty) { auto required_alignment_of = [&](const sem::Type* ty) {
@ -385,22 +386,22 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
return symbols_.NameFor(sm->Declaration()->symbol); return symbols_.NameFor(sm->Declaration()->symbol);
}; };
// Cache result of type + storage class pair. // Cache result of type + address space pair.
if (!layouts.emplace(store_ty, sc).second) { if (!layouts.emplace(store_ty, address_space).second) {
return true; return true;
} }
if (!ast::IsHostShareable(sc)) { if (!ast::IsHostShareable(address_space)) {
return true; return true;
} }
// Temporally forbid using f16 types in "uniform" and "storage" storage class. // Temporally forbid using f16 types in "uniform" and "storage" address space.
// TODO(tint:1473, tint:1502): Remove this error after f16 is supported in "uniform" and // TODO(tint:1473, tint:1502): Remove this error after f16 is supported in "uniform" and
// "storage" storage class but keep for "push_constant" storage class. // "storage" address space but keep for "push_constant" address space.
if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty))) { if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty))) {
AddError( AddError("using f16 types in '" + utils::ToString(address_space) +
"using f16 types in '" + utils::ToString(sc) + "' storage class is not implemented yet", "' address space is not implemented yet",
source); source);
return false; return false;
} }
@ -410,7 +411,8 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
uint32_t required_align = required_alignment_of(m->Type()); uint32_t required_align = required_alignment_of(m->Type());
// Recurse into the member type. // Recurse into the member type.
if (!StorageClassLayout(m->Type(), sc, m->Declaration()->type->source, layouts)) { if (!AddressSpaceLayout(m->Type(), address_space, m->Declaration()->type->source,
layouts)) {
AddNote("see layout of struct:\n" + str->Layout(symbols_), AddNote("see layout of struct:\n" + str->Layout(symbols_),
str->Declaration()->source); str->Declaration()->source);
return false; return false;
@ -420,7 +422,7 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
if (m->Offset() % required_align != 0) { if (m->Offset() % required_align != 0) {
AddError("the offset of a struct member of type '" + AddError("the offset of a struct member of type '" +
m->Type()->UnwrapRef()->FriendlyName(symbols_) + m->Type()->UnwrapRef()->FriendlyName(symbols_) +
"' in storage class '" + utils::ToString(sc) + "' in address space '" + utils::ToString(address_space) +
"' must be a multiple of " + std::to_string(required_align) + "' must be a multiple of " + std::to_string(required_align) +
" bytes, but '" + member_name_of(m) + "' is currently at offset " + " bytes, but '" + member_name_of(m) + "' is currently at offset " +
std::to_string(m->Offset()) + ". Consider setting @align(" + std::to_string(m->Offset()) + ". Consider setting @align(" +
@ -474,11 +476,11 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
// TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested // TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested
// element type here, but we can't easily get that from the semantic node. // element type here, but we can't easily get that from the semantic node.
// We should consider recursing through the AST type nodes instead. // We should consider recursing through the AST type nodes instead.
if (!StorageClassLayout(arr->ElemType(), sc, source, layouts)) { if (!AddressSpaceLayout(arr->ElemType(), address_space, source, layouts)) {
return false; return false;
} }
if (sc == ast::StorageClass::kUniform) { if (address_space == ast::AddressSpace::kUniform) {
// We already validated that this array member is itself aligned to 16 // We already validated that this array member is itself aligned to 16
// bytes above, so we only need to validate that stride is a multiple // bytes above, so we only need to validate that stride is a multiple
// of 16 bytes. // of 16 bytes.
@ -516,22 +518,22 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
return true; return true;
} }
bool Validator::StorageClassLayout(const sem::Variable* var, bool Validator::AddressSpaceLayout(const sem::Variable* var,
const ast::Extensions& enabled_extensions, const ast::Extensions& enabled_extensions,
ValidTypeStorageLayouts& layouts) const { ValidTypeStorageLayouts& layouts) const {
if (var->StorageClass() == ast::StorageClass::kPushConstant && if (var->AddressSpace() == ast::AddressSpace::kPushConstant &&
!enabled_extensions.Contains(ast::Extension::kChromiumExperimentalPushConstant) && !enabled_extensions.Contains(ast::Extension::kChromiumExperimentalPushConstant) &&
IsValidationEnabled(var->Declaration()->attributes, IsValidationEnabled(var->Declaration()->attributes,
ast::DisabledValidation::kIgnoreStorageClass)) { ast::DisabledValidation::kIgnoreAddressSpace)) {
AddError( AddError(
"use of variable storage class 'push_constant' requires enabling extension " "use of variable address space 'push_constant' requires enabling extension "
"'chromium_experimental_push_constant'", "'chromium_experimental_push_constant'",
var->Declaration()->source); var->Declaration()->source);
return false; return false;
} }
if (auto* str = var->Type()->UnwrapRef()->As<sem::Struct>()) { if (auto* str = var->Type()->UnwrapRef()->As<sem::Struct>()) {
if (!StorageClassLayout(str, var->StorageClass(), str->Declaration()->source, layouts)) { if (!AddressSpaceLayout(str, var->AddressSpace(), str->Declaration()->source, layouts)) {
AddNote("see declaration of variable", var->Declaration()->source); AddNote("see declaration of variable", var->Declaration()->source);
return false; return false;
} }
@ -540,7 +542,7 @@ bool Validator::StorageClassLayout(const sem::Variable* var,
if (var->Declaration()->type) { if (var->Declaration()->type) {
source = var->Declaration()->type->source; source = var->Declaration()->type->source;
} }
if (!StorageClassLayout(var->Type()->UnwrapRef(), var->StorageClass(), source, layouts)) { if (!AddressSpaceLayout(var->Type()->UnwrapRef(), var->AddressSpace(), source, layouts)) {
return false; return false;
} }
} }
@ -559,7 +561,7 @@ bool Validator::LocalVariable(const sem::Variable* local) const {
decl, // decl, //
[&](const ast::Var* var) { [&](const ast::Var* var) {
if (IsValidationEnabled(var->attributes, if (IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreStorageClass)) { ast::DisabledValidation::kIgnoreAddressSpace)) {
if (!local->Type()->UnwrapRef()->IsConstructible()) { if (!local->Type()->UnwrapRef()->IsConstructible()) {
AddError("function-scope 'var' must have a constructible type", AddError("function-scope 'var' must have a constructible type",
var->type ? var->type->source : var->source); var->type ? var->type->source : var->source);
@ -583,7 +585,7 @@ bool Validator::GlobalVariable(
const std::unordered_map<OverrideId, const sem::Variable*>& override_ids, const std::unordered_map<OverrideId, const sem::Variable*>& override_ids,
const std::unordered_map<const sem::Type*, const Source&>& atomic_composite_info) const { const std::unordered_map<const sem::Type*, const Source&>& atomic_composite_info) const {
auto* decl = global->Declaration(); auto* decl = global->Declaration();
if (global->StorageClass() != ast::StorageClass::kWorkgroup && if (global->AddressSpace() != ast::AddressSpace::kWorkgroup &&
IsArrayWithOverrideCount(global->Type())) { IsArrayWithOverrideCount(global->Type())) {
RaiseArrayWithOverrideCountError(decl->type ? decl->type->source RaiseArrayWithOverrideCountError(decl->type ? decl->type->source
: decl->constructor->source); : decl->constructor->source);
@ -599,8 +601,8 @@ bool Validator::GlobalVariable(
return false; return false;
} }
if (global->StorageClass() == ast::StorageClass::kNone) { if (global->AddressSpace() == ast::AddressSpace::kNone) {
AddError("module-scope 'var' declaration must have a storage class", decl->source); AddError("module-scope 'var' declaration must have a address space", decl->source);
return false; return false;
} }
@ -608,11 +610,11 @@ bool Validator::GlobalVariable(
bool is_shader_io_attribute = bool is_shader_io_attribute =
attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute, attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute,
ast::InvariantAttribute, ast::LocationAttribute>(); ast::InvariantAttribute, ast::LocationAttribute>();
bool has_io_storage_class = global->StorageClass() == ast::StorageClass::kIn || bool has_io_address_space = global->AddressSpace() == ast::AddressSpace::kIn ||
global->StorageClass() == ast::StorageClass::kOut; global->AddressSpace() == ast::AddressSpace::kOut;
if (!attr->IsAnyOf<ast::BindingAttribute, ast::GroupAttribute, if (!attr->IsAnyOf<ast::BindingAttribute, ast::GroupAttribute,
ast::InternalAttribute>() && ast::InternalAttribute>() &&
(!is_shader_io_attribute || !has_io_storage_class)) { (!is_shader_io_attribute || !has_io_address_space)) {
AddError("attribute '" + attr->Name() + "' is not valid for module-scope 'var'", AddError("attribute '" + attr->Name() + "' is not valid for module-scope 'var'",
attr->source); attr->source);
return false; return false;
@ -621,9 +623,9 @@ bool Validator::GlobalVariable(
// https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration // https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration
// The access mode always has a default, and except for variables in the // The access mode always has a default, and except for variables in the
// storage storage class, must not be written. // storage address space, must not be written.
if (var->declared_access != ast::Access::kUndefined) { if (var->declared_access != ast::Access::kUndefined) {
if (global->StorageClass() == ast::StorageClass::kStorage) { if (global->AddressSpace() == ast::AddressSpace::kStorage) {
// The access mode for the storage address space can only be 'read' or // The access mode for the storage address space can only be 'read' or
// 'read_write'. // 'read_write'.
if (var->declared_access == ast::Access::kWrite) { if (var->declared_access == ast::Access::kWrite) {
@ -632,7 +634,7 @@ bool Validator::GlobalVariable(
return false; return false;
} }
} else { } else {
AddError("only variables in <storage> storage class may declare an access mode", AddError("only variables in <storage> address space may declare an access mode",
decl->source); decl->source);
return false; return false;
} }
@ -672,15 +674,15 @@ bool Validator::GlobalVariable(
return false; return false;
} }
if (global->StorageClass() == ast::StorageClass::kFunction) { if (global->AddressSpace() == ast::AddressSpace::kFunction) {
AddError("module-scope 'var' must not use storage class 'function'", decl->source); AddError("module-scope 'var' must not use address space 'function'", decl->source);
return false; return false;
} }
switch (global->StorageClass()) { switch (global->AddressSpace()) {
case ast::StorageClass::kUniform: case ast::AddressSpace::kUniform:
case ast::StorageClass::kStorage: case ast::AddressSpace::kStorage:
case ast::StorageClass::kHandle: { case ast::AddressSpace::kHandle: {
// https://gpuweb.github.io/gpuweb/wgsl/#resource-interface // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
// Each resource variable must be declared with both group and binding // Each resource variable must be declared with both group and binding
// attributes. // attributes.
@ -712,29 +714,32 @@ bool Validator::GlobalVariable(
bool Validator::AtomicVariable( bool Validator::AtomicVariable(
const sem::Variable* var, const sem::Variable* var,
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const { std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const {
auto sc = var->StorageClass(); auto address_space = var->AddressSpace();
auto* decl = var->Declaration(); auto* decl = var->Declaration();
auto access = var->Access(); auto access = var->Access();
auto* type = var->Type()->UnwrapRef(); auto* type = var->Type()->UnwrapRef();
auto source = decl->type ? decl->type->source : decl->source; auto source = decl->type ? decl->type->source : decl->source;
if (type->Is<sem::Atomic>()) { if (type->Is<sem::Atomic>()) {
if (sc != ast::StorageClass::kWorkgroup && sc != ast::StorageClass::kStorage) { if (address_space != ast::AddressSpace::kWorkgroup &&
AddError("atomic variables must have <storage> or <workgroup> storage class", source); address_space != ast::AddressSpace::kStorage) {
AddError("atomic variables must have <storage> or <workgroup> address space", source);
return false; return false;
} }
} else if (type->IsAnyOf<sem::Struct, sem::Array>()) { } else if (type->IsAnyOf<sem::Struct, sem::Array>()) {
auto found = atomic_composite_info.find(type); auto found = atomic_composite_info.find(type);
if (found != atomic_composite_info.end()) { if (found != atomic_composite_info.end()) {
if (sc != ast::StorageClass::kStorage && sc != ast::StorageClass::kWorkgroup) { if (address_space != ast::AddressSpace::kStorage &&
AddError("atomic variables must have <storage> or <workgroup> storage class", address_space != ast::AddressSpace::kWorkgroup) {
AddError("atomic variables must have <storage> or <workgroup> address space",
source); source);
AddNote("atomic sub-type of '" + sem_.TypeNameOf(type) + "' is declared here", AddNote("atomic sub-type of '" + sem_.TypeNameOf(type) + "' is declared here",
found->second); found->second);
return false; return false;
} else if (sc == ast::StorageClass::kStorage && access != ast::Access::kReadWrite) { } else if (address_space == ast::AddressSpace::kStorage &&
access != ast::Access::kReadWrite) {
AddError( AddError(
"atomic variables in <storage> storage class must have read_write " "atomic variables in <storage> address space must have read_write "
"access mode", "access mode",
source); source);
AddNote("atomic sub-type of '" + sem_.TypeNameOf(type) + "' is declared here", AddNote("atomic sub-type of '" + sem_.TypeNameOf(type) + "' is declared here",
@ -756,21 +761,21 @@ bool Validator::Var(const sem::Variable* v) const {
return false; return false;
} }
if (storage_ty->is_handle() && var->declared_storage_class != ast::StorageClass::kNone) { if (storage_ty->is_handle() && var->declared_address_space != ast::AddressSpace::kNone) {
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the // If the store type is a texture type or a sampler type, then the
// variable declaration must not have a storage class attribute. The // variable declaration must not have a address space attribute. The
// storage class will always be handle. // address space will always be handle.
AddError( AddError(
"variables of type '" + sem_.TypeNameOf(storage_ty) + "' must not have a storage class", "variables of type '" + sem_.TypeNameOf(storage_ty) + "' must not have a address space",
var->source); var->source);
return false; return false;
} }
if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreStorageClass) && if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreAddressSpace) &&
(var->declared_storage_class == ast::StorageClass::kIn || (var->declared_address_space == ast::AddressSpace::kIn ||
var->declared_storage_class == ast::StorageClass::kOut)) { var->declared_address_space == ast::AddressSpace::kOut)) {
AddError("invalid use of input/output storage class", var->source); AddError("invalid use of input/output address space", var->source);
return false; return false;
} }
return true; return true;
@ -873,12 +878,14 @@ bool Validator::Parameter(const ast::Function* func, const sem::Variable* var) c
} }
if (auto* ref = var->Type()->As<sem::Pointer>()) { if (auto* ref = var->Type()->As<sem::Pointer>()) {
auto sc = ref->StorageClass(); auto address_space = ref->AddressSpace();
if (!(sc == ast::StorageClass::kFunction || sc == ast::StorageClass::kPrivate || if (!(address_space == ast::AddressSpace::kFunction ||
sc == ast::StorageClass::kWorkgroup) && address_space == ast::AddressSpace::kPrivate ||
IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreStorageClass)) { address_space == ast::AddressSpace::kWorkgroup) &&
IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreAddressSpace)) {
std::stringstream ss; std::stringstream ss;
ss << "function parameter of pointer type cannot be in '" << sc << "' storage class"; ss << "function parameter of pointer type cannot be in '" << address_space
<< "' address space";
AddError(ss.str(), decl->source); AddError(ss.str(), decl->source);
return false; return false;
} }
@ -1954,7 +1961,7 @@ bool Validator::PipelineStages(const std::vector<sem::Function*>& entry_points)
auto stage = entry_point->Declaration()->PipelineStage(); auto stage = entry_point->Declaration()->PipelineStage();
if (stage != ast::PipelineStage::kCompute) { if (stage != ast::PipelineStage::kCompute) {
for (auto* var : func->DirectlyReferencedGlobals()) { for (auto* var : func->DirectlyReferencedGlobals()) {
if (var->StorageClass() == ast::StorageClass::kWorkgroup) { if (var->AddressSpace() == ast::AddressSpace::kWorkgroup) {
std::stringstream stage_name; std::stringstream stage_name;
stage_name << stage; stage_name << stage;
for (auto* user : var->Users()) { for (auto* user : var->Users()) {
@ -2042,7 +2049,7 @@ bool Validator::PushConstants(const std::vector<sem::Function*>& entry_points) c
auto check_push_constant = [&](const sem::Function* func, const sem::Function* ep) { auto check_push_constant = [&](const sem::Function* func, const sem::Function* ep) {
for (auto* var : func->DirectlyReferencedGlobals()) { for (auto* var : func->DirectlyReferencedGlobals()) {
if (var->StorageClass() != ast::StorageClass::kPushConstant || if (var->AddressSpace() != ast::AddressSpace::kPushConstant ||
var == push_constant_var) { var == push_constant_var) {
continue; continue;
} }

View File

@ -72,7 +72,7 @@ namespace tint::resolver {
class Validator { class Validator {
public: public:
/// The valid type storage layouts typedef /// The valid type storage layouts typedef
using ValidTypeStorageLayouts = std::set<std::pair<const sem::Type*, ast::StorageClass>>; using ValidTypeStorageLayouts = std::set<std::pair<const sem::Type*, ast::AddressSpace>>;
/// Constructor /// Constructor
/// @param builder the program builder /// @param builder the program builder
@ -389,12 +389,12 @@ class Validator {
/// Validates a variable initializer /// Validates a variable initializer
/// @param v the variable to validate /// @param v the variable to validate
/// @param storage_class the storage class of the variable /// @param address_space the address space of the variable
/// @param storage_type the type of the storage /// @param storage_type the type of the storage
/// @param initializer the RHS initializer expression /// @param initializer the RHS initializer expression
/// @returns true on succes, false otherwise /// @returns true on succes, false otherwise
bool VariableInitializer(const ast::Variable* v, bool VariableInitializer(const ast::Variable* v,
ast::StorageClass storage_class, ast::AddressSpace address_space,
const sem::Type* storage_type, const sem::Type* storage_type,
const sem::Expression* initializer) const; const sem::Expression* initializer) const;
@ -427,23 +427,23 @@ class Validator {
/// @returns true on success, false otherwise. /// @returns true on success, false otherwise.
bool NoDuplicateAttributes(utils::VectorRef<const ast::Attribute*> attributes) const; bool NoDuplicateAttributes(utils::VectorRef<const ast::Attribute*> attributes) const;
/// Validates a storage class layout /// Validates a address space layout
/// @param type the type to validate /// @param type the type to validate
/// @param sc the storage class /// @param sc the address space
/// @param source the source of the type /// @param source the source of the type
/// @param layouts previously validated storage layouts /// @param layouts previously validated storage layouts
/// @returns true on success, false otherwise /// @returns true on success, false otherwise
bool StorageClassLayout(const sem::Type* type, bool AddressSpaceLayout(const sem::Type* type,
ast::StorageClass sc, ast::AddressSpace sc,
Source source, Source source,
ValidTypeStorageLayouts& layouts) const; ValidTypeStorageLayouts& layouts) const;
/// Validates a storage class layout /// Validates a address space layout
/// @param var the variable to validate /// @param var the variable to validate
/// @param layouts previously validated storage layouts /// @param layouts previously validated storage layouts
/// @param enabled_extensions all the extensions declared in current module /// @param enabled_extensions all the extensions declared in current module
/// @returns true on success, false otherwise. /// @returns true on success, false otherwise.
bool StorageClassLayout(const sem::Variable* var, bool AddressSpaceLayout(const sem::Variable* var,
const ast::Extensions& enabled_extensions, const ast::Extensions& enabled_extensions,
ValidTypeStorageLayouts& layouts) const; ValidTypeStorageLayouts& layouts) const;

View File

@ -78,7 +78,7 @@ TEST_F(ValidatorIsStorableTest, Matrix) {
} }
TEST_F(ValidatorIsStorableTest, Pointer) { TEST_F(ValidatorIsStorableTest, Pointer) {
auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::StorageClass::kPrivate, auto* ptr = create<sem::Pointer>(create<sem::I32>(), ast::AddressSpace::kPrivate,
ast::Access::kReadWrite); ast::Access::kReadWrite);
EXPECT_FALSE(v()->IsStorable(ptr)); EXPECT_FALSE(v()->IsStorable(ptr));
} }

View File

@ -238,7 +238,7 @@ TEST_F(ResolverVariableTest, LocalVar_ShadowsGlobalVar) {
// var a = a; // var a = a;
// } // }
auto* g = GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate); auto* g = GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
auto* v = Var("a", Expr("a")); auto* v = Var("a", Expr("a"));
Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(v)}); Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(v)});
@ -419,7 +419,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
auto* b = Let("b", ty.bool_(), b_c); auto* b = Let("b", ty.bool_(), b_c);
auto* s = Let("s", ty.Of(S), s_c); auto* s = Let("s", ty.Of(S), s_c);
auto* a = Let("a", ty.Of(A), a_c); auto* a = Let("a", ty.Of(A), a_c);
auto* p = Let("p", ty.pointer<i32>(ast::StorageClass::kFunction), p_c); auto* p = Let("p", ty.pointer<i32>(ast::AddressSpace::kFunction), p_c);
Func("F", utils::Empty, ty.void_(), Func("F", utils::Empty, ty.void_(),
utils::Vector{ utils::Vector{
@ -470,7 +470,7 @@ TEST_F(ResolverVariableTest, LocalLet_InheritsAccessFromOriginatingVariable) {
// } // }
auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())}); auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())});
auto* buf = Structure("S", utils::Vector{Member("inner", ty.Of(inner))}); auto* buf = Structure("S", utils::Vector{Member("inner", ty.Of(inner))});
auto* storage = GlobalVar("s", ty.Of(buf), ast::StorageClass::kStorage, ast::Access::kReadWrite, auto* storage = GlobalVar("s", ty.Of(buf), ast::AddressSpace::kStorage, ast::Access::kReadWrite,
Binding(0_a), Group(0_a)); Binding(0_a), Group(0_a));
auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 3_i); auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 3_i);
@ -552,7 +552,7 @@ TEST_F(ResolverVariableTest, LocalLet_ShadowsGlobalVar) {
// let a = a; // let a = a;
// } // }
auto* g = GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate); auto* g = GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
auto* l = Let("a", Expr("a")); auto* l = Let("a", Expr("a"));
Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(l)}); Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(l)});
@ -762,7 +762,7 @@ TEST_F(ResolverVariableTest, LocalConst_ShadowsGlobalVar) {
// const a = 1i; // const a = 1i;
// } // }
auto* g = GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate); auto* g = GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
auto* c = Const("a", Expr(1_i)); auto* c = Const("a", Expr(1_i));
Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(c)}); Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(c)});
@ -1030,16 +1030,16 @@ TEST_F(ResolverVariableTest, DISABLED_LocalConst_ConstEval) {
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Module-scope 'var' // Module-scope 'var'
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_F(ResolverVariableTest, GlobalVar_StorageClass) { TEST_F(ResolverVariableTest, GlobalVar_AddressSpace) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())}); auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())});
auto* private_ = GlobalVar("p", ty.i32(), ast::StorageClass::kPrivate); auto* private_ = GlobalVar("p", ty.i32(), ast::AddressSpace::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::StorageClass::kWorkgroup); auto* workgroup = GlobalVar("w", ty.i32(), ast::AddressSpace::kWorkgroup);
auto* uniform = auto* uniform =
GlobalVar("ub", ty.Of(buf), ast::StorageClass::kUniform, Binding(0_a), Group(0_a)); GlobalVar("ub", ty.Of(buf), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
auto* storage = auto* storage =
GlobalVar("sb", ty.Of(buf), ast::StorageClass::kStorage, Binding(1_a), Group(0_a)); GlobalVar("sb", ty.Of(buf), ast::AddressSpace::kStorage, Binding(1_a), Group(0_a));
auto* handle = auto* handle =
GlobalVar("h", ty.depth_texture(ast::TextureDimension::k2d), Binding(2_a), Group(0_a)); GlobalVar("h", ty.depth_texture(ast::TextureDimension::k2d), Binding(2_a), Group(0_a));
@ -1058,11 +1058,11 @@ TEST_F(ResolverVariableTest, GlobalVar_StorageClass) {
EXPECT_EQ(TypeOf(handle)->As<sem::Reference>()->Access(), ast::Access::kRead); EXPECT_EQ(TypeOf(handle)->As<sem::Reference>()->Access(), ast::Access::kRead);
} }
TEST_F(ResolverVariableTest, GlobalVar_ExplicitStorageClass) { TEST_F(ResolverVariableTest, GlobalVar_ExplicitAddressSpace) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())}); auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())});
auto* storage = GlobalVar("sb", ty.Of(buf), ast::StorageClass::kStorage, auto* storage = GlobalVar("sb", ty.Of(buf), ast::AddressSpace::kStorage,
ast::Access::kReadWrite, Binding(1_a), Group(0_a)); ast::Access::kReadWrite, Binding(1_a), Group(0_a));
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -1220,7 +1220,7 @@ TEST_F(ResolverVariableTest, Param_ShadowsGlobalVar) {
// fn F(a : bool) { // fn F(a : bool) {
// } // }
auto* g = GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate); auto* g = GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
auto* p = Param("a", ty.bool_()); auto* p = Param("a", ty.bool_());
Func("F", utils::Vector{p}, ty.void_(), utils::Empty); Func("F", utils::Vector{p}, ty.void_(), utils::Empty);

Some files were not shown because too many files have changed in this diff Show More