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:**
```
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;
^^^^
@ -72,7 +72,7 @@ shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is
**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;
^^^^

View File

@ -12,7 +12,7 @@ Specification work in the WebGPU group hasn't started.
## 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 variable declarations must not have an initializer.
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
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
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
TODO(dsinclair): Nested if's
# Storage classes
# Address spaces
TODO(dsinclair): do ...
# Storage buffers
@ -155,7 +155,7 @@ TODO(dsinclair): Rewrite with bools
## MSL
TODO(dsinclair): Rewrite with bools
# Input / Output storage class
# Input / Output address spaces
## HLSL
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
// 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;
DAWN_TRY_ASSIGN(shaderModule, utils::CreateShaderModule(device, R"(
struct UniformParams {
@ -258,7 +258,7 @@ ComputePassEncoder::TransformIndirectDispatchBuffer(Ref<BufferBase> indirectBuff
kDispatchIndirectSize + clientOffsetFromAlignedBoundary;
// 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'.
struct UniformParams {
uint32_t maxComputeWorkgroupsPerDimension;

View File

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

View File

@ -180,6 +180,8 @@ libtint_source_set("libtint_core_all_src") {
sources = [
"ast/access.cc",
"ast/access.h",
"ast/address_space.cc",
"ast/address_space.h",
"ast/alias.cc",
"ast/alias.h",
"ast/array.cc",
@ -312,8 +314,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/statement.h",
"ast/static_assert.cc",
"ast/static_assert.h",
"ast/storage_class.cc",
"ast/storage_class.h",
"ast/storage_texture.cc",
"ast/storage_texture.h",
"ast/stride_attribute.cc",
@ -998,6 +998,7 @@ if (tint_build_unittests) {
tint_unittests_source_set("tint_unittests_ast_src") {
sources = [
"ast/address_space_test.cc",
"ast/alias_test.cc",
"ast/array_test.cc",
"ast/assignment_statement_test.cc",
@ -1054,7 +1055,6 @@ if (tint_build_unittests) {
"ast/sampler_test.cc",
"ast/stage_attribute_test.cc",
"ast/static_assert_test.cc",
"ast/storage_class_test.cc",
"ast/storage_texture_test.cc",
"ast/stride_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") {
sources = [
"resolver/address_space_layout_validation_test.cc",
"resolver/address_space_validation_test.cc",
"resolver/array_accessor_test.cc",
"resolver/assignment_validation_test.cc",
"resolver/atomics_test.cc",
@ -1133,11 +1135,9 @@ if (tint_build_unittests) {
"resolver/side_effects_test.cc",
"resolver/source_variable_test.cc",
"resolver/static_assert_test.cc",
"resolver/storage_class_layout_validation_test.cc",
"resolver/storage_class_validation_test.cc",
"resolver/struct_address_space_use_test.cc",
"resolver/struct_layout_test.cc",
"resolver/struct_pipeline_stage_use_test.cc",
"resolver/struct_storage_class_use_test.cc",
"resolver/type_constructor_validation_test.cc",
"resolver/type_validation_test.cc",
"resolver/uniformity_test.cc",
@ -1354,6 +1354,7 @@ if (tint_build_unittests) {
sources = [
"reader/wgsl/lexer_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_assignment_stmt_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_statement_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_struct_attribute_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/static_assert.cc
ast/static_assert.h
ast/storage_class.cc
ast/storage_class.h
ast/address_space.cc
ast/address_space.h
ast/storage_texture.cc
ast/storage_texture.h
ast/stride_attribute.cc
@ -747,7 +747,7 @@ if(TINT_BUILD_TESTS)
ast/sampler_test.cc
ast/stage_attribute_test.cc
ast/static_assert_test.cc
ast/storage_class_test.cc
ast/address_space_test.cc
ast/storage_texture_test.cc
ast/stride_attribute_test.cc
ast/struct_member_align_attribute_test.cc
@ -814,11 +814,11 @@ if(TINT_BUILD_TESTS)
resolver/side_effects_test.cc
resolver/static_assert_test.cc
resolver/source_variable_test.cc
resolver/storage_class_layout_validation_test.cc
resolver/storage_class_validation_test.cc
resolver/address_space_layout_validation_test.cc
resolver/address_space_validation_test.cc
resolver/struct_layout_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_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_statement_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_struct_body_decl_test.cc
reader/wgsl/parser_impl_struct_decl_test.cc
@ -1300,7 +1300,7 @@ if(TINT_BUILD_BENCHMARKS)
set(TINT_BENCHMARK_SRC
"castable_bench.cc"
"ast/extension_bench.cc"
"ast/storage_class_bench.cc"
"ast/address_space_bench.cc"
"ast/texel_format_bench.cc"
"bench/benchmark.cc"
"reader/wgsl/parser_bench.cc"

View File

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

View File

@ -15,20 +15,20 @@
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/src/cmd/gen
// using the template:
// src/tint/ast/storage_class.h.tmpl
// src/tint/ast/address_space.h.tmpl
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
#ifndef SRC_TINT_AST_STORAGE_CLASS_H_
#define SRC_TINT_AST_STORAGE_CLASS_H_
#ifndef SRC_TINT_AST_ADDRESS_SPACE_H_
#define SRC_TINT_AST_ADDRESS_SPACE_H_
#include <ostream>
namespace tint::ast {
/// Storage class of a given pointer.
enum class StorageClass {
/// Address space of a given pointer.
enum class AddressSpace {
kInvalid,
kNone, // Tint-internal enum entry - not parsed
kFunction,
@ -43,23 +43,24 @@ enum class StorageClass {
};
/// @param out the std::ostream to write to
/// @param value the StorageClass
/// @param value the AddressSpace
/// @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
/// @returns the parsed enum, or StorageClass::kInvalid if the string could not be parsed.
StorageClass ParseStorageClass(std::string_view str);
/// @returns the parsed enum, or AddressSpace::kInvalid if the string could not be parsed.
AddressSpace ParseAddressSpace(std::string_view str);
/// @returns true if the StorageClass is host-shareable
/// @param sc the StorageClass
/// @returns true if the AddressSpace is host-shareable
/// @param address_space the AddressSpace
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
inline bool IsHostShareable(StorageClass sc) {
return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage ||
sc == ast::StorageClass::kPushConstant;
inline bool IsHostShareable(AddressSpace address_space) {
return address_space == ast::AddressSpace::kUniform ||
address_space == ast::AddressSpace::kStorage ||
address_space == ast::AddressSpace::kPushConstant;
}
} // 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:
./tools/run gen
@ -12,26 +12,26 @@ See:
*/ -}}
{{- Import "src/tint/templates/enums.tmpl.inc" -}}
{{- $enum := (Sem.Enum "storage_class") -}}
{{- $enum := (Sem.Enum "address_space") -}}
#ifndef SRC_TINT_AST_STORAGE_CLASS_H_
#define SRC_TINT_AST_STORAGE_CLASS_H_
#ifndef SRC_TINT_AST_ADDRESS_SPACE_H_
#define SRC_TINT_AST_ADDRESS_SPACE_H_
#include <ostream>
namespace tint::ast {
/// Storage class of a given pointer.
/// Address space of a given pointer.
{{ Eval "DeclareEnum" $enum}}
/// @returns true if the StorageClass is host-shareable
/// @param sc the StorageClass
/// @returns true if the AddressSpace is host-shareable
/// @param address_space the AddressSpace
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
inline bool IsHostShareable(StorageClass sc) {
return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage ||
sc == ast::StorageClass::kPushConstant;
inline bool IsHostShareable(AddressSpace address_space) {
return address_space == ast::AddressSpace::kUniform || address_space == ast::AddressSpace::kStorage ||
address_space == ast::AddressSpace::kPushConstant;
}
} // 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
// 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
////////////////////////////////////////////////////////////////////////////////
#include "src/tint/ast/storage_class.h"
#include "src/tint/ast/address_space.h"
#include <array>
@ -29,7 +29,7 @@
namespace tint::ast {
namespace {
void StorageClassParser(::benchmark::State& state) {
void AddressSpaceParser(::benchmark::State& state) {
std::array kStrings{
"fccnctin",
"ucti3",
@ -76,13 +76,13 @@ void StorageClassParser(::benchmark::State& state) {
};
for (auto _ : state) {
for (auto& str : kStrings) {
auto result = ParseStorageClass(str);
auto result = ParseAddressSpace(str);
benchmark::DoNotOptimize(result);
}
}
}
BENCHMARK(StorageClassParser);
BENCHMARK(AddressSpaceParser);
} // namespace
} // 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:
./tools/run gen
@ -12,9 +12,9 @@ See:
*/ -}}
{{- 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>

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:
./tools/run gen
@ -12,9 +12,9 @@ See:
*/ -}}
{{- 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>

View File

@ -33,8 +33,8 @@ std::string DisableValidationAttribute::InternalName() const {
return "disable_validation__function_has_no_body";
case DisabledValidation::kBindingPointCollision:
return "disable_validation__binding_point_collision";
case DisabledValidation::kIgnoreStorageClass:
return "disable_validation__ignore_storage_class";
case DisabledValidation::kIgnoreAddressSpace:
return "disable_validation__ignore_address_space";
case DisabledValidation::kEntryPointParameter:
return "disable_validation__entry_point_parameter";
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
/// variables have the same binding points.
kBindingPointCollision,
/// When applied to a variable, the validator will not complain about the declared storage
/// class.
kIgnoreStorageClass,
/// When applied to a variable, the validator will not complain about the declared address
/// space.
kIgnoreAddressSpace,
/// When applied to an entry-point function parameter, the validator will not check for entry IO
/// attributes.
kEntryPointParameter,

View File

@ -72,7 +72,7 @@ TEST_F(ModuleTest, Assert_DifferentProgramID_GlobalVariable) {
{
ProgramBuilder b1;
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");
}
@ -92,7 +92,7 @@ TEST_F(ModuleTest, CloneOrder) {
ProgramBuilder b;
b.Func("F", {}, b.ty.void_(), {});
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));
}();

View File

@ -24,15 +24,15 @@ Pointer::Pointer(ProgramID pid,
NodeID nid,
const Source& src,
const Type* const subtype,
ast::StorageClass sc,
ast::AddressSpace addr_space,
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::ostringstream out;
out << "ptr<";
if (storage_class != ast::StorageClass::kNone) {
out << storage_class << ", ";
if (address_space != ast::AddressSpace::kNone) {
out << address_space << ", ";
}
out << type->FriendlyName(symbols);
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
auto src = ctx->Clone(source);
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

View File

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

View File

@ -24,21 +24,21 @@ using AstPointerTest = TestHelper;
TEST_F(AstPointerTest, Creation) {
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->storage_class, ast::StorageClass::kStorage);
EXPECT_EQ(p->address_space, ast::AddressSpace::kStorage);
EXPECT_EQ(p->access, Access::kRead);
}
TEST_F(AstPointerTest, FriendlyName) {
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>");
}
TEST_F(AstPointerTest, FriendlyNameWithAccess) {
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>");
}

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

View File

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

View File

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

View File

@ -25,10 +25,10 @@ namespace {
using VariableTest = TestHelper;
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->declared_storage_class, StorageClass::kFunction);
EXPECT_EQ(v->declared_address_space, AddressSpace::kFunction);
EXPECT_TRUE(v->type->Is<ast::I32>());
EXPECT_EQ(v->source.range.begin.line, 0u);
EXPECT_EQ(v->source.range.begin.column, 0u);
@ -38,10 +38,10 @@ TEST_F(VariableTest, Creation) {
TEST_F(VariableTest, CreationWithSource) {
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->declared_storage_class, StorageClass::kPrivate);
EXPECT_EQ(v->declared_address_space, AddressSpace::kPrivate);
EXPECT_TRUE(v->type->Is<ast::F32>());
EXPECT_EQ(v->source.range.begin.line, 27u);
EXPECT_EQ(v->source.range.begin.column, 4u);
@ -51,10 +51,10 @@ TEST_F(VariableTest, CreationWithSource) {
TEST_F(VariableTest, CreationEmpty) {
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->declared_storage_class, StorageClass::kWorkgroup);
EXPECT_EQ(v->declared_address_space, AddressSpace::kWorkgroup);
EXPECT_TRUE(v->type->Is<ast::I32>());
EXPECT_EQ(v->source.range.begin.line, 27u);
EXPECT_EQ(v->source.range.begin.column, 4u);
@ -92,7 +92,7 @@ TEST_F(VariableTest, Assert_DifferentProgramID_Constructor) {
}
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));
auto& attributes = var->attributes;
@ -107,22 +107,22 @@ TEST_F(VariableTest, WithAttributes) {
}
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());
}
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());
}
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());
}
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());
}

View File

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

View File

@ -565,7 +565,7 @@ uint32_t Inspector::GetWorkgroupStorageSize(const std::string& entry_point) {
uint32_t total_size = 0;
auto* func_sem = program_->Sem().Get(func);
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();
uint32_t align = ty->Align();
uint32_t size = ty->Size();

View File

@ -126,11 +126,11 @@ void InspectorBuilder::AddUniformBuffer(const std::string& name,
const ast::Type* type,
uint32_t group,
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) {
GlobalVar(name, type, ast::StorageClass::kWorkgroup);
GlobalVar(name, type, ast::AddressSpace::kWorkgroup);
}
void InspectorBuilder::AddStorageBuffer(const std::string& name,
@ -138,7 +138,7 @@ void InspectorBuilder::AddStorageBuffer(const std::string& name,
ast::Access access,
uint32_t group,
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)));
}
@ -188,7 +188,7 @@ void InspectorBuilder::AddResource(const std::string& name,
}
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(

View File

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

View File

@ -172,14 +172,14 @@ class ProgramBuilder {
~VarOptions();
const ast::Type* type = nullptr;
ast::StorageClass storage = ast::StorageClass::kNone;
ast::AddressSpace address_space = ast::AddressSpace::kNone;
ast::Access access = ast::Access::kUndefined;
const ast::Expression* constructor = nullptr;
utils::Vector<const ast::Attribute*, 4> attributes;
private:
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(const ast::Expression* c) { constructor = c; }
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 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
/// @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,
ast::StorageClass storage_class,
ast::AddressSpace address_space,
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 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
/// @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::Type* type,
ast::StorageClass storage_class,
ast::AddressSpace address_space,
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
/// @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>
const ast::Pointer* pointer(ast::StorageClass storage_class,
const ast::Pointer* pointer(ast::AddressSpace address_space,
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 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
/// @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>
const ast::Pointer* pointer(const Source& source,
ast::StorageClass storage_class,
ast::AddressSpace address_space,
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
@ -1651,7 +1651,7 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order:
/// * 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::Expression* - specifies the variable's initializer expression
/// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
@ -1661,8 +1661,8 @@ class ProgramBuilder {
template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
VarOptions opts(std::forward<OPTIONS>(options)...);
return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.storage, opts.access,
opts.constructor, std::move(opts.attributes));
return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.address_space,
opts.access, opts.constructor, std::move(opts.attributes));
}
/// @param source the variable source
@ -1670,17 +1670,18 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order:
/// * 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::Expression* - specifies the variable's initializer expression
/// * 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.
/// @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>
const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
VarOptions opts(std::forward<OPTIONS>(options)...);
return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type, opts.storage,
opts.access, opts.constructor, std::move(opts.attributes));
return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type,
opts.address_space, opts.access, opts.constructor,
std::move(opts.attributes));
}
/// @param name the variable name
@ -1773,7 +1774,7 @@ class ProgramBuilder {
/// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order:
/// * 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::Expression* - specifies the variable's initializer expression
/// * 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
/// Can be any of the following, in any order:
/// * 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::Expression* - specifies the variable's initializer expression
/// * 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) {
GlobalVar("var", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("var", ty.f32(), ast::AddressSpace::kPrivate);
Program program(std::move(*this));
EXPECT_TRUE(program.IsValid());

View File

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

View File

@ -16,9 +16,9 @@
#define SRC_TINT_READER_SPIRV_ENUM_CONVERTER_H_
#include "spirv/unified1/spirv.h"
#include "src/tint/ast/address_space.h"
#include "src/tint/ast/builtin_value.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/sem/storage_texture.h"
@ -39,11 +39,11 @@ class EnumConverter {
/// @returns a Tint AST pipeline stage
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
/// @param sc the SPIR-V storage class
/// @returns a Tint AST storage class
ast::StorageClass ToStorageClass(const SpvStorageClass sc);
/// @returns a Tint AST address space
ast::AddressSpace ToAddressSpace(const SpvStorageClass sc);
/// Converts a SPIR-V Builtin value a Tint Builtin.
/// On failure, logs an error and returns kNone

View File

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

View File

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

View File

@ -325,12 +325,12 @@ struct DefInfo {
/// example, pointers. crbug.com/tint/98
bool requires_hoisted_var_def = false;
/// The storage class to use for this value, if it is of pointer type.
/// This is required to carry a storage class override from a storage
/// buffer expressed in the old style (with Uniform storage class)
/// that needs to be remapped to StorageBuffer storage class.
/// The address space to use for this value, if it is of pointer type.
/// This is required to carry an address space override from a storage
/// buffer expressed in the old style (with Uniform address space)
/// that needs to be remapped to StorageBuffer address space.
/// 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.
/// 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")
<< " requires_hoisted_var_def: " << (di.requires_hoisted_var_def ? "true" : "false");
if (di.storage_class != ast::StorageClass::kNone) {
o << " sc:" << int(di.storage_class);
if (di.address_space != ast::AddressSpace::kNone) {
o << " sc:" << int(di.address_space);
}
switch (di.skip) {
case SkipReason::kDontSkip:
@ -470,7 +470,7 @@ class FunctionEmitter {
/// by the `index_prefix`, which successively indexes into the variable.
/// Also generates the assignment statements that copy the input parameter
/// 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_type The store type of the variable
/// @param decos The variable's decorations
@ -496,8 +496,7 @@ class FunctionEmitter {
/// expressions that compute the value they contribute to the entry point
/// return value. The part of the output variable is specfied
/// by the `index_prefix`, which successively indexes into the variable.
/// Assumes the variable has already been created in the Private storage
/// class.
/// Assumes the variable has already been created in the Private address space
/// @param var_name The name of the variable
/// @param var_type The store type of the variable
/// @param decos The variable's decorations
@ -612,19 +611,19 @@ class FunctionEmitter {
/// @returns false on failure
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.
/// @param id a SPIR-V ID for a pointer value
/// @returns the storage class
ast::StorageClass GetStorageClassForPointerValue(uint32_t id);
/// @returns the address space
ast::AddressSpace GetAddressSpaceForPointerValue(uint32_t id);
/// Remaps the storage class for the type of a locally-defined value,
/// if necessary. If it's not a pointer type, or if its storage class
/// Remaps the address space for the type of a locally-defined value,
/// 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.
/// @param type the AST type
/// @param result_id the SPIR-V ID for the locally defined value
/// @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'
/// 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);
/// 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,
/// it changes a storage class of "none" to "function".
/// or reference type, ensures the address space is not defaulted. That is,
/// it changes a address space of "none" to "function".
/// @param expr a typed expression
/// @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.
/// @param inst the SPIR-V instruction

View File

@ -818,11 +818,11 @@ fn main() {
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,
// 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
// 'function' storage class. From crbug.com/tint/807
// 'function' address space. From crbug.com/tint/807
const std::string assembly = R"(
OpCapability Shader
OpMemoryModel Logical Simple
@ -993,7 +993,7 @@ TEST_F(SpvParserMemoryTest, RemapStorageBuffer_ThroughAccessChain_Cascaded) {
TEST_F(SpvParserMemoryTest, RemapStorageBuffer_ThroughCopyObject_WithoutHoisting) {
// 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
// value type for the const declration.
const auto assembly = OldStorageBufferPreamble() + R"(

View File

@ -1205,28 +1205,28 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
return nullptr;
}
auto ast_storage_class = enum_converter_.ToStorageClass(storage_class);
if (ast_storage_class == ast::StorageClass::kInvalid) {
auto ast_address_space = enum_converter_.ToAddressSpace(storage_class);
if (ast_address_space == ast::AddressSpace::kInvalid) {
Fail() << "SPIR-V pointer type with ID " << type_id << " has invalid storage class "
<< static_cast<uint32_t>(storage_class);
return nullptr;
}
if (ast_storage_class == ast::StorageClass::kUniform &&
if (ast_address_space == ast::AddressSpace::kUniform &&
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);
}
// Pipeline input and output variables map to private variables.
if (ast_storage_class == ast::StorageClass::kIn ||
ast_storage_class == ast::StorageClass::kOut) {
ast_storage_class = ast::StorageClass::kPrivate;
if (ast_address_space == ast::AddressSpace::kIn ||
ast_address_space == ast::AddressSpace::kOut) {
ast_address_space = ast::AddressSpace::kPrivate;
}
switch (ptr_as) {
case PtrAs::Ref:
return ty_.Reference(ast_elem_ty, ast_storage_class);
return ty_.Reference(ast_elem_ty, ast_address_space);
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);
return nullptr;
@ -1443,15 +1443,15 @@ bool ParserImpl::EmitModuleScopeVariables() {
var.NumInOperands() > 1 ? var.GetSingleWordInOperand(1) : 0u;
continue;
}
switch (enum_converter_.ToStorageClass(spirv_storage_class)) {
case ast::StorageClass::kNone:
case ast::StorageClass::kIn:
case ast::StorageClass::kOut:
case ast::StorageClass::kUniform:
case ast::StorageClass::kHandle:
case ast::StorageClass::kStorage:
case ast::StorageClass::kWorkgroup:
case ast::StorageClass::kPrivate:
switch (enum_converter_.ToAddressSpace(spirv_storage_class)) {
case ast::AddressSpace::kNone:
case ast::AddressSpace::kIn:
case ast::AddressSpace::kOut:
case ast::AddressSpace::kUniform:
case ast::AddressSpace::kHandle:
case ast::AddressSpace::kStorage:
case ast::AddressSpace::kWorkgroup:
case ast::AddressSpace::kPrivate:
break;
default:
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_storage_class = ast_type->As<Pointer>()->storage_class;
auto ast_address_space = ast_type->As<Pointer>()->address_space;
const ast::Expression* ast_constructor = nullptr;
if (var.NumInOperands() > 1) {
// SPIR-V initializers are always constants.
@ -1489,7 +1489,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
// here.)
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);
// TODO(dneto): initializers (a.k.a. constructor expression)
if (ast_var) {
@ -1522,7 +1522,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
}
auto* ast_var =
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, {});
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::StorageClass sc,
ast::AddressSpace address_space,
const Type* storage_type,
const ast::Expression* constructor,
AttributeList decorations) {
@ -1564,7 +1564,7 @@ ast::Var* ParserImpl::MakeVar(uint32_t id,
}
ast::Access access = ast::Access::kUndefined;
if (sc == ast::StorageClass::kStorage) {
if (address_space == ast::AddressSpace::kStorage) {
bool read_only = false;
if (auto* tn = storage_type->As<Named>()) {
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
// storage class, so we don't mention the storage class.
if (sc == ast::StorageClass::kHandle) {
sc = ast::StorageClass::kNone;
// address space, so we don't mention the address space.
if (address_space == ast::AddressSpace::kHandle) {
address_space = ast::AddressSpace::kNone;
}
if (!ConvertDecorationsForVariable(id, &storage_type, &decorations,
sc != ast::StorageClass::kPrivate)) {
address_space != ast::AddressSpace::kPrivate)) {
return nullptr;
}
auto sym = builder_.Symbols().Register(namer_.Name(id));
return create<ast::Var>(Source{}, sym, storage_type->Build(builder_), sc, access, constructor,
decorations);
return create<ast::Var>(Source{}, sym, storage_type->Build(builder_), address_space, access,
constructor, decorations);
}
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.
auto* result = ty_.Pointer(ast_store_type, ast::StorageClass::kHandle);
auto* result = ty_.Pointer(ast_store_type, ast::AddressSpace::kHandle);
// Remember it for later.
handle_type_[&var] = 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
/// 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
/// - samplers
/// - 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
/// an ignorable builtin variable.
/// @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 constructor the variable constructor
/// @param decorations the variable decorations
/// @returns a new Variable node, or null in the ignorable variable case and
/// in the error case
ast::Var* MakeVar(uint32_t id,
ast::StorageClass sc,
ast::AddressSpace address_space,
const Type* storage_type,
const ast::Expression* constructor,
AttributeList decorations);
@ -583,7 +583,7 @@ class ParserImpl : Reader {
/// The ID of the type of a pointer to the struct in the Output storage
/// class class.
uint32_t pointer_type_id = 0;
/// The SPIR-V storage class.
/// The SPIR-V address space.
SpvStorageClass storage_class = SpvStorageClassOutput;
/// The ID of the type of a pointer to the Position member.
uint32_t position_member_pointer_type_id = 0;
@ -640,8 +640,8 @@ class ParserImpl : Reader {
Usage GetHandleUsage(uint32_t id) const;
/// Returns the SPIR-V type for the sampler or image type for the given
/// variable in UniformConstant storage class, or function parameter pointing
/// into the UniformConstant storage class . Returns null and emits an
/// variable in UniformConstant address space, or function parameter pointing
/// into the UniformConstant address space . Returns null and emits an
/// error on failure.
/// @param var the OpVariable instruction or OpFunctionParameter
/// @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);
/// 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.
/// @param var the OpVariable instruction
/// @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
// - a pointer type to one of these
// These are the types "enclosing" a buffer block with the old style
// representation: using Uniform storage class and BufferBlock decoration
// on the struct. The new style is to use the StorageBuffer storage class
// representation: using Uniform address space and BufferBlock decoration
// on the struct. The new style is to use the StorageBuffer address space
// and Block decoration.
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"));
}
TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidStorageClass) {
// Disallow invalid storage class
TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidAddressSpace) {
// Disallow invalid address space
auto p = parser(test::Assemble(Preamble() + R"(
%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()));
// TODO(dneto): I can't get it past module building.
EXPECT_FALSE(p->BuildInternalModule()) << p->error();
@ -731,7 +731,7 @@ TEST_F(SpvParserTest, ConvertType_PointerInput) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -747,7 +747,7 @@ TEST_F(SpvParserTest, ConvertType_PointerOutput) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -763,7 +763,7 @@ TEST_F(SpvParserTest, ConvertType_PointerUniform) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -779,7 +779,7 @@ TEST_F(SpvParserTest, ConvertType_PointerWorkgroup) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -795,7 +795,7 @@ TEST_F(SpvParserTest, ConvertType_PointerUniformConstant) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -811,7 +811,7 @@ TEST_F(SpvParserTest, ConvertType_PointerStorageBuffer) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -827,7 +827,7 @@ TEST_F(SpvParserTest, ConvertType_PointerPrivate) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -843,7 +843,7 @@ TEST_F(SpvParserTest, ConvertType_PointerFunction) {
auto* ptr_ty = type->As<Pointer>();
EXPECT_NE(ptr_ty, nullptr);
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());
}
@ -862,12 +862,12 @@ TEST_F(SpvParserTest, ConvertType_PointerToPointer) {
auto* ptr_ty = type->As<Pointer>();
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>());
auto* ptr_ptr_ty = ptr_ty->type->As<Pointer>();
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(p->error().empty());

View File

@ -119,7 +119,7 @@ TEST_F(SpvModuleScopeVarParserTest, NoVar) {
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"(
%float = OpTypeFloat 32
%ptr = OpTypePointer CrossWorkgroup %float
@ -135,7 +135,7 @@ TEST_F(SpvModuleScopeVarParserTest, BadStorageClass_NotAWebGPUStorageClass) {
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"(
%float = OpTypeFloat 32
%ptr = OpTypePointer Function %float

View File

@ -50,11 +50,11 @@ namespace tint::reader::spirv {
namespace {
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 {
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 {
@ -107,10 +107,10 @@ struct StorageTextureHasher {
// Equality operators
//! @cond Doxygen_Suppress
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) {
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) {
return a.type == b.type && a.size == b.size;
@ -170,14 +170,14 @@ Type::~Type() = 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;
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;
const ast::Type* Reference::Build(ProgramBuilder& b) const {
@ -438,12 +438,12 @@ const spirv::I32* TypeManager::I32() {
return state->i32_;
}
const spirv::Pointer* TypeManager::Pointer(const Type* el, ast::StorageClass sc) {
return state->pointers_.Get(el, sc);
const spirv::Pointer* TypeManager::Pointer(const Type* el, ast::AddressSpace address_space) {
return state->pointers_.Get(el, address_space);
}
const spirv::Reference* TypeManager::Reference(const Type* el, ast::StorageClass sc) {
return state->references_.Get(el, sc);
const spirv::Reference* TypeManager::Reference(const Type* el, ast::AddressSpace address_space) {
return state->references_.Get(el, address_space);
}
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::stringstream ss;
ss << "ptr<" << utils::ToString(storage_class) << ", " << type->String() + ">";
ss << "ptr<" << utils::ToString(address_space) << ", " << type->String() + ">";
return ss.str();
}
std::string Reference::String() const {
std::stringstream ss;
ss << "ref<" + utils::ToString(storage_class) << ", " << type->String() << ">";
ss << "ref<" + utils::ToString(address_space) << ", " << type->String() << ">";
return ss.str();
}

View File

@ -20,8 +20,8 @@
#include <vector>
#include "src/tint/ast/access.h"
#include "src/tint/ast/address_space.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/texture.h"
#include "src/tint/castable.h"
@ -161,8 +161,8 @@ struct I32 final : public Castable<I32, Type> {
struct Pointer final : public Castable<Pointer, Type> {
/// Constructor
/// @param ty the store type
/// @param sc the pointer storage class
Pointer(const Type* ty, ast::StorageClass sc);
/// @param sc the pointer address space
Pointer(const Type* ty, ast::AddressSpace sc);
/// Copy constructor
/// @param other the other type to copy
@ -179,8 +179,8 @@ struct Pointer final : public Castable<Pointer, Type> {
/// the store type
Type const* const type;
/// the pointer storage class
ast::StorageClass const storage_class;
/// the pointer address space
ast::AddressSpace const address_space;
};
/// `ref<SC, T>` type
@ -189,8 +189,8 @@ struct Pointer final : public Castable<Pointer, Type> {
struct Reference final : public Castable<Reference, Type> {
/// Constructor
/// @param ty the referenced type
/// @param sc the reference storage class
Reference(const Type* ty, ast::StorageClass sc);
/// @param sc the reference address space
Reference(const Type* ty, ast::AddressSpace sc);
/// Copy constructor
/// @param other the other type to copy
@ -207,8 +207,8 @@ struct Reference final : public Castable<Reference, Type> {
/// the store type
Type const* const type;
/// the pointer storage class
ast::StorageClass const storage_class;
/// the pointer address space
ast::AddressSpace const address_space;
};
/// `vecN<T>` type
@ -534,15 +534,15 @@ class TypeManager {
/// @return a I32 type. Repeated calls will return the same pointer.
const spirv::I32* I32();
/// @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
/// 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 sc the reference storage class
/// @param address_space the reference address space
/// @return a Reference type. Repeated calls with the same arguments will
/// 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 sz the number of elements in the vector
/// @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.F32(), ty.F32());
EXPECT_EQ(ty.I32(), ty.I32());
EXPECT_EQ(ty.Pointer(ty.I32(), ast::StorageClass::kNone),
ty.Pointer(ty.I32(), ast::StorageClass::kNone));
EXPECT_EQ(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
ty.Pointer(ty.I32(), ast::AddressSpace::kNone));
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.Array(ty.I32(), 3, 2), ty.Array(ty.I32(), 3, 2));
@ -53,10 +53,10 @@ TEST(SpvParserTypeTest, DifferentArgumentsGivesDifferentPointer) {
Symbol sym_b(Symbol(2, {}));
TypeManager ty;
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone),
ty.Pointer(ty.U32(), ast::StorageClass::kNone));
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone),
ty.Pointer(ty.I32(), ast::StorageClass::kIn));
EXPECT_NE(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
ty.Pointer(ty.U32(), ast::AddressSpace::kNone));
EXPECT_NE(ty.Pointer(ty.I32(), ast::AddressSpace::kNone),
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.I32(), 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,
std::string name_in,
ast::StorageClass storage_class_in,
ast::AddressSpace address_space_in,
ast::Access access_in,
const ast::Type* type_in)
: source(std::move(source_in)),
name(std::move(name_in)),
storage_class(storage_class_in),
address_space(address_space_in),
access(access_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
builder_.Symbols().Register(decl->name), // symbol
decl->type, // type
decl->storage_class, // storage class
decl->address_space, // address space
decl->access, // access control
initializer, // initializer
std::move(attrs)); // attributes
@ -697,7 +697,7 @@ Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl() {
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
@ -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) {
const char* use = "ptr declaration";
auto storage_class = ast::StorageClass::kNone;
auto address_space = ast::AddressSpace::kNone;
auto access = ast::Access::kUndefined;
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) {
return Failure::kErrored;
}
storage_class = sc.value;
address_space = sc.value;
if (!expect(use, Token::Type::kComma)) {
return Failure::kErrored;
@ -1242,7 +1242,7 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_pointer(const Source& s) {
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
@ -1329,19 +1329,19 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(const Source& s,
// | 'storage'
//
// 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 ident = expect_ident("storage class");
auto ident = expect_ident("address space");
if (ident.errored) {
return Failure::kErrored;
}
auto storage_class = ast::ParseStorageClass(ident.value);
if (storage_class == ast::StorageClass::kInvalid) {
return add_error(t.source(), "invalid storage class", use);
auto address_space = ast::ParseAddressSpace(ident.value);
if (address_space == ast::AddressSpace::kInvalid) {
return add_error(t.source(), "invalid address space", use);
}
return {storage_class, t.source()};
return {address_space, t.source()};
}
// struct_decl
@ -1988,7 +1988,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_statement() {
auto* var = create<ast::Var>(decl->source, // source
builder_.Symbols().Register(decl->name), // symbol
decl->type, // type
decl->storage_class, // storage class
decl->address_space, // address space
decl->access, // access control
initializer, // initializer
utils::Empty); // attributes

View File

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

View File

@ -17,18 +17,18 @@
namespace tint::reader::wgsl {
namespace {
struct StorageClassData {
struct AddressSpaceData {
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);
return out;
}
class ParserStorageClassTest : public ParserImplTestWithParam<StorageClassData> {};
class ParserAddressSpaceTest : public ParserImplTestWithParam<AddressSpaceData> {};
TEST_P(ParserStorageClassTest, Parses) {
TEST_P(ParserAddressSpaceTest, Parses) {
auto params = GetParam();
auto p = parser(params.input);
@ -42,19 +42,19 @@ TEST_P(ParserStorageClassTest, Parses) {
}
INSTANTIATE_TEST_SUITE_P(
ParserImplTest,
ParserStorageClassTest,
testing::Values(StorageClassData{"uniform", ast::StorageClass::kUniform},
StorageClassData{"workgroup", ast::StorageClass::kWorkgroup},
StorageClassData{"storage", ast::StorageClass::kStorage},
StorageClassData{"private", ast::StorageClass::kPrivate},
StorageClassData{"function", ast::StorageClass::kFunction}));
ParserAddressSpaceTest,
testing::Values(AddressSpaceData{"uniform", ast::AddressSpace::kUniform},
AddressSpaceData{"workgroup", ast::AddressSpace::kWorkgroup},
AddressSpaceData{"storage", ast::AddressSpace::kStorage},
AddressSpaceData{"private", ast::AddressSpace::kPrivate},
AddressSpaceData{"function", ast::AddressSpace::kFunction}));
TEST_F(ParserImplTest, StorageClass_NoMatch) {
auto p = parser("not-a-storage-class");
TEST_F(ParserImplTest, AddressSpace_NoMatch) {
auto p = parser("not-a-address-space");
auto sc = p->expect_address_space("test");
EXPECT_EQ(sc.errored, true);
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

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>;",
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>;
^^^^
)");
@ -1139,7 +1139,7 @@ var i : atomic<u32 x;
TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) {
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
^^^^
)");

View File

@ -31,7 +31,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
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.column, 14u);
@ -55,7 +55,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
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.column, 14u);
@ -81,7 +81,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(var->type, nullptr);
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.column, 36u);
@ -112,7 +112,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithAttribute_MulitpleGroups) {
EXPECT_EQ(var->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(var->type, nullptr);
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.column, 36u);
@ -165,7 +165,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched);
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

View File

@ -176,7 +176,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr) {
auto* ptr = t.value->As<ast::Pointer>();
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}}));
}
@ -191,7 +191,7 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_WithAccess) {
auto* ptr = t.value->As<ast::Pointer>();
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);
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>();
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>();
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");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterStorageClass) {
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAddressSpace) {
auto p = parser("ptr<function f32>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
@ -265,14 +265,14 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingCommaAfterAccess) {
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 t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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) {
@ -302,17 +302,17 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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 t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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) {

View File

@ -167,7 +167,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr) {
auto* ptr = t.value->As<ast::Pointer>();
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}}));
}
@ -182,7 +182,7 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_WithAccess) {
auto* ptr = t.value->As<ast::Pointer>();
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);
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>();
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>();
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");
}
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterStorageClass) {
TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAddressSpace) {
auto p = parser("ptr<function f32>");
auto t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored);
@ -256,14 +256,14 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingCommaAfterAccess) {
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 t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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) {
@ -293,17 +293,17 @@ TEST_F(ParserImplTest, TypeDeclWithoutIdent_Ptr_MissingParams) {
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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 t = p->type_decl_without_ident();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
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) {

View File

@ -72,7 +72,7 @@ TEST_F(ParserImplTest, VariableDecl_MissingVar) {
ASSERT_TRUE(t.IsIdentifier());
}
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
TEST_F(ParserImplTest, VariableDecl_WithAddressSpace) {
auto p = parser("var<private> my_var : f32");
auto v = p->variable_decl();
EXPECT_TRUE(v.matched);
@ -80,7 +80,7 @@ TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
EXPECT_FALSE(p->has_error());
EXPECT_EQ(v->name, "my_var");
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.column, 14u);
@ -96,16 +96,16 @@ TEST_F(ParserImplTest, VariableDecl_WithPushConstant) {
EXPECT_FALSE(p->has_error());
EXPECT_EQ(v->name, "my_var");
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 v = p->variable_decl();
EXPECT_FALSE(v.matched);
EXPECT_TRUE(v.errored);
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

View File

@ -19,7 +19,7 @@ namespace {
struct VariableStorageData {
const char* input;
ast::StorageClass storage_class;
ast::AddressSpace address_space;
ast::Access access;
};
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> {};
TEST_P(VariableQualifierTest, ParsesStorageClass) {
TEST_P(VariableQualifierTest, ParsesAddressSpace) {
auto params = GetParam();
auto p = parser(std::string("<") + params.input + ">");
@ -37,7 +37,7 @@ TEST_P(VariableQualifierTest, ParsesStorageClass) {
EXPECT_FALSE(p->has_error());
EXPECT_FALSE(sc.errored);
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);
auto& t = p->next();
@ -47,14 +47,14 @@ INSTANTIATE_TEST_SUITE_P(
ParserImplTest,
VariableQualifierTest,
testing::Values(
VariableStorageData{"uniform", ast::StorageClass::kUniform, ast::Access::kUndefined},
VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup, ast::Access::kUndefined},
VariableStorageData{"storage", ast::StorageClass::kStorage, ast::Access::kUndefined},
VariableStorageData{"private", ast::StorageClass::kPrivate, ast::Access::kUndefined},
VariableStorageData{"function", ast::StorageClass::kFunction, ast::Access::kUndefined},
VariableStorageData{"storage, read", ast::StorageClass::kStorage, ast::Access::kRead},
VariableStorageData{"storage, write", ast::StorageClass::kStorage, ast::Access::kWrite},
VariableStorageData{"storage, read_write", ast::StorageClass::kStorage,
VariableStorageData{"uniform", ast::AddressSpace::kUniform, ast::Access::kUndefined},
VariableStorageData{"workgroup", ast::AddressSpace::kWorkgroup, ast::Access::kUndefined},
VariableStorageData{"storage", ast::AddressSpace::kStorage, ast::Access::kUndefined},
VariableStorageData{"private", ast::AddressSpace::kPrivate, ast::Access::kUndefined},
VariableStorageData{"function", ast::AddressSpace::kFunction, ast::Access::kUndefined},
VariableStorageData{"storage, read", ast::AddressSpace::kStorage, ast::Access::kRead},
VariableStorageData{"storage, write", ast::AddressSpace::kStorage, ast::Access::kWrite},
VariableStorageData{"storage, read_write", ast::AddressSpace::kStorage,
ast::Access::kReadWrite}));
TEST_F(ParserImplTest, VariableQualifier_NoMatch) {
@ -63,7 +63,7 @@ TEST_F(ParserImplTest, VariableQualifier_NoMatch) {
EXPECT_TRUE(p->has_error());
EXPECT_TRUE(sc.errored);
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) {
@ -72,7 +72,7 @@ TEST_F(ParserImplTest, VariableQualifier_Empty) {
EXPECT_TRUE(p->has_error());
EXPECT_TRUE(sc.errored);
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) {

View File

@ -22,10 +22,10 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::resolver {
namespace {
using ResolverStorageClassLayoutValidationTest = ResolverTest;
using ResolverAddressSpaceLayoutValidationTest = ResolverTest;
// Detect unaligned member for storage buffers
TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, StorageBuffer_UnalignedMember) {
// struct S {
// @size(5) a : 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)}),
});
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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:
/* align(4) size(12) */ struct S {
/* offset(0) align(4) size( 5) */ a : f32;
@ -55,7 +55,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember)
78:90 note: see declaration of variable)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, StorageBuffer_UnalignedMember_SuggestedFix) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, StorageBuffer_UnalignedMember_SuggestedFix) {
// struct S {
// @size(5) a : 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)}),
});
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
// Detect unaligned struct member for uniform buffers
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_Struct) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_UnalignedMember_Struct) {
// struct Inner {
// scalar : i32;
// };
@ -100,13 +100,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_S
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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:
/* align(4) size(8) */ struct Outer {
/* 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)");
}
TEST_F(ResolverStorageClassLayoutValidationTest,
TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_UnalignedMember_Struct_SuggestedFix) {
// struct Inner {
// scalar : i32;
@ -145,14 +145,14 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
// 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>;
//
// struct Outer {
@ -170,13 +170,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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:
/* align(4) size(164) */ struct Outer {
/* 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)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_Array_SuggestedFix) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_UnalignedMember_Array_SuggestedFix) {
// type Inner = @stride(16) array<f32, 10u>;
//
// struct Outer {
@ -204,7 +204,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_UnalignedMember_A
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));
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
// multiple of 16 bytes
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotMultipleOf16) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_MembersOffsetNotMultipleOf16) {
// struct Inner {
// @align(1) @size(5) scalar : i32;
// };
@ -236,7 +236,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotM
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));
ASSERT_FALSE(r()->Resolve());
@ -257,7 +257,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_MembersOffsetNotM
}
// See https://crbug.com/tint/1344
TEST_F(ResolverStorageClassLayoutValidationTest,
TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_MembersOffsetNotMultipleOf16_InnerMoreMembersThanOuter) {
// struct Inner {
// a : i32;
@ -288,7 +288,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
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));
ASSERT_FALSE(r()->Resolve());
@ -311,7 +311,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
22:24 note: see declaration of variable)");
}
TEST_F(ResolverStorageClassLayoutValidationTest,
TEST_F(ResolverAddressSpaceLayoutValidationTest,
UniformBuffer_MembersOffsetNotMultipleOf16_SuggestedFix) {
// struct Inner {
// @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)}),
});
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));
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
// 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 {
// v : vec3<f32>;
// s : f32;
@ -358,13 +358,13 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_Vec3MemberOffset_
});
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();
}
// 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>;
//
// struct Outer {
@ -383,7 +383,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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));
ASSERT_FALSE(r()->Resolve());
@ -398,7 +398,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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>;
//
// struct Outer {
@ -417,7 +417,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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));
ASSERT_FALSE(r()->Resolve());
@ -433,7 +433,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_Struct) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_Struct) {
// struct ArrayElem {
// a : f32;
// b : i32;
@ -460,7 +460,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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));
ASSERT_FALSE(r()->Resolve());
@ -475,11 +475,11 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
78:90 note: see declaration of variable)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_TopLevelArray) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_TopLevelArray) {
// @group(0) @binding(0)
// var<uniform> a : array<f32, 4u>;
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());
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.)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStride_NestedArray) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_NestedArray) {
// struct Outer {
// 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)),
});
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));
ASSERT_FALSE(r()->Resolve());
@ -514,7 +514,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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>;
//
// struct Outer {
@ -533,14 +533,14 @@ TEST_F(ResolverStorageClassLayoutValidationTest, UniformBuffer_InvalidArrayStrid
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
// Detect unaligned member for push constants buffers
TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, PushConstant_UnalignedMember) {
// enable chromium_experimental_push_constant;
// struct S {
// @size(5) a : f32;
@ -552,12 +552,12 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) {
Source{{12, 34}}, "S",
utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}),
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());
EXPECT_EQ(
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:
/* align(4) size(12) */ struct S {
/* offset(0) align(4) size( 5) */ a : f32;
@ -567,7 +567,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_UnalignedMember) {
78:90 note: see declaration of variable)");
}
TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_Aligned) {
TEST_F(ResolverAddressSpaceLayoutValidationTest, PushConstant_Aligned) {
// enable chromium_experimental_push_constant;
// struct S {
// @size(5) a : f32;
@ -577,7 +577,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest, PushConstant_Aligned) {
Enable(ast::Extension::kChromiumExperimentalPushConstant);
Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(5_a)}),
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();
}

View File

@ -25,169 +25,169 @@ namespace {
using ::testing::HasSubstr;
using ResolverStorageClassValidationTest = ResolverTest;
using ResolverAddressSpaceValidationTest = ResolverTest;
TEST_F(ResolverStorageClassValidationTest, GlobalVariableNoStorageClass_Fail) {
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariableNoAddressSpace_Fail) {
// var g : f32;
GlobalVar(Source{{12, 34}}, "g", ty.f32());
EXPECT_FALSE(r()->Resolve());
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;
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_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) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::StorageClass::kPrivate);
TEST_F(ResolverAddressSpaceValidationTest, Private_RuntimeArray) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
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)");
}
TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArrayInStruct) {
TEST_F(ResolverAddressSpaceValidationTest, Private_RuntimeArrayInStruct) {
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_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
12:34 note: while instantiating 'var' v)");
}
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArray) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::StorageClass::kWorkgroup);
TEST_F(ResolverAddressSpaceValidationTest, Workgroup_RuntimeArray) {
GlobalVar(Source{{12, 34}}, "v", ty.array(ty.i32()), ast::AddressSpace::kWorkgroup);
EXPECT_FALSE(r()->Resolve());
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)");
}
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArrayInStruct) {
TEST_F(ResolverAddressSpaceValidationTest, Workgroup_RuntimeArrayInStruct) {
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_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
12:34 note: while instantiating 'var' v)");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferBool) {
// 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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferBoolAlias) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferBoolAlias) {
// type a = bool;
// var<storage, read> g : a;
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
// F16 types in storage and uniform buffer is not implemented yet.
// 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;
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());
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");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferF16Alias_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16Alias_TemporallyBan) {
// type a = f16;
// var<storage, read> g : a;
Enable(ast::Extension::kF16);
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));
ASSERT_FALSE(r()->Resolve());
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");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferVectorF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF16_TemporallyBan) {
// var<storage> g : vec4<f16>;
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));
ASSERT_FALSE(r()->Resolve());
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");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferArrayF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF16_TemporallyBan) {
// struct S { a : f16 };
// var<storage, read> g : array<S, 3u>;
Enable(ast::Extension::kF16);
auto* s = Structure("S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}))});
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());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'storage' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'storage' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferStructF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructF16_TemporallyBan) {
// struct S { x : f16 };
// var<storage, read> g : S;
Enable(ast::Extension::kF16);
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferNoErrorStructF16Aliases_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructF16Aliases_TemporallyBan) {
// struct S { x : f16 };
// type a1 = S;
// 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* a1 = Alias("a1", ty.Of(s));
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferPointer) {
// var<storage> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate),
ast::StorageClass::kStorage, Binding(0_a), Group(0_a));
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::AddressSpace::kStorage, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferIntScalar) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferIntScalar) {
// 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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferVectorF32) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF32) {
// 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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferArrayF32) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF32) {
// var<storage, read> g : array<S, 3u>;
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, NotStorage_AccessMode) {
TEST_F(ResolverAddressSpaceValidationTest, NotStorage_AccessMode) {
// 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());
EXPECT_EQ(
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;
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));
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;
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));
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;
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));
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)");
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferStructI32) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructI32) {
// struct S { x : i32 };
// var<storage, read> g : S;
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));
ASSERT_TRUE(r()->Resolve());
}
TEST_F(ResolverStorageClassValidationTest, StorageBufferNoErrorStructI32Aliases) {
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructI32Aliases) {
// struct S { x : i32 };
// type a1 = S;
// var<storage, read> g : a1;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
auto* a1 = Alias("a1", ty.Of(s));
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));
ASSERT_TRUE(r()->Resolve());
}
TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBuffer_Struct_Runtime) {
// struct S { m: array<f32>; };
// @group(0) @binding(0) var<uniform, > svar : S;
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));
ASSERT_FALSE(r()->Resolve());
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
56:78 note: while instantiating 'var' svar)");
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferBool) {
// 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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferBoolAlias) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferBoolAlias) {
// type a = bool;
// var<uniform> g : a;
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
// F16 types in storage and uniform buffer is not implemented yet.
// 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;
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());
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");
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferF16Alias_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16Alias_TemporallyBan) {
// type a = f16;
// var<uniform> g : a;
Enable(ast::Extension::kF16);
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));
ASSERT_FALSE(r()->Resolve());
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");
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferVectorF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF16_TemporallyBan) {
// var<uniform> g : vec4<f16>;
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF16_TemporallyBan) {
// struct S {
// @size(16) f : f16;
// }
@ -402,29 +402,29 @@ TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF16_TemporallyBan)
auto* s = Structure(
"S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}), utils::Vector{MemberSize(16_a)})});
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());
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructF16_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16_TemporallyBan) {
// struct S { x : f16 };
// var<uniform> g : S;
Enable(ast::Extension::kF16);
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());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructF16Aliases_TemporallyBan) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16Aliases_TemporallyBan) {
// struct S { x : f16 };
// type a1 = S;
// 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* 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());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' storage "
"class is not implemented yet"));
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
"space is not implemented yet"));
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferPointer) {
// var<uniform> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate),
ast::StorageClass::kUniform, Binding(0_a), Group(0_a));
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferIntScalar) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferIntScalar) {
// 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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferVectorF32) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF32) {
// 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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferArrayF32) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF32) {
// struct S {
// @size(16) f : f32;
// }
// var<uniform> g : array<S, 3u>;
auto* s = Structure("S", utils::Vector{Member("a", ty.f32(), utils::Vector{MemberSize(16_a)})});
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();
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructI32) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructI32) {
// struct S { x : i32 };
// var<uniform> g : S;
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, UniformBufferStructI32Aliases) {
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructI32Aliases) {
// struct S { x : i32 };
// type a1 = S;
// var<uniform> g : a1;
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, PushConstantBool) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantBool) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : bool;
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());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, PushConstantF16) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantF16) {
// enable chromium_experimental_push_constant;
// enable f16;
// var<push_constant> g : f16;
Enable(ast::Extension::kF16);
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());
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");
}
TEST_F(ResolverStorageClassValidationTest, PushConstantPointer) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantPointer) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : ptr<private, f32>;
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::StorageClass::kPrivate),
ast::StorageClass::kPushConstant);
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
ast::AddressSpace::kPushConstant);
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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)");
}
TEST_F(ResolverStorageClassValidationTest, PushConstantIntScalar) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantIntScalar) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : i32;
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("g", ty.i32(), ast::StorageClass::kPushConstant);
GlobalVar("g", ty.i32(), ast::AddressSpace::kPushConstant);
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverStorageClassValidationTest, PushConstantVectorF32) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantVectorF32) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : vec4<f32>;
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();
}
TEST_F(ResolverStorageClassValidationTest, PushConstantArrayF32) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantArrayF32) {
// enable chromium_experimental_push_constant;
// struct S { a : f32}
// var<push_constant> g : array<S, 3u>;
Enable(ast::Extension::kChromiumExperimentalPushConstant);
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
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();
}
TEST_F(ResolverStorageClassValidationTest, PushConstantWithInitializer) {
TEST_F(ResolverAddressSpaceValidationTest, PushConstantWithInitializer) {
// enable chromium_experimental_push_constant;
// var<push_constant> a : u32 = 0u;
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)));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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

View File

@ -27,7 +27,7 @@ namespace {
using ResolverIndexAccessorTest = ResolverTest;
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));
WrapInFunction(acc);
@ -36,7 +36,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
}
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* acc = IndexAccessor("my_var", idx);
WrapInFunction(Decl(idx), acc);
@ -50,7 +50,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_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* idy = Var("idy", ty.u32(), Expr(2_u));
auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy);
@ -100,7 +100,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_BothDimension_Dynamic) {
}
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);
WrapInFunction(acc);
@ -121,7 +121,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix) {
}
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);
WrapInFunction(acc);
@ -141,7 +141,7 @@ TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) {
}
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));
WrapInFunction(acc);
@ -150,7 +150,7 @@ TEST_F(ResolverIndexAccessorTest, Vector_F32) {
}
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* acc = IndexAccessor("my_var", idx);
WrapInFunction(Decl(idx), acc);
@ -173,7 +173,7 @@ TEST_F(ResolverIndexAccessorTest, Vector_Dynamic) {
}
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);
WrapInFunction(acc);
@ -193,7 +193,7 @@ TEST_F(ResolverIndexAccessorTest, Vector) {
}
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);
WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -209,7 +209,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) {
}
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);
WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -225,7 +225,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_u32) {
}
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);
WrapInFunction(acc);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -243,7 +243,7 @@ TEST_F(ResolverIndexAccessorTest, Array_Literal_AInt) {
TEST_F(ResolverIndexAccessorTest, Alias_Array) {
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);
WrapInFunction(acc);
@ -337,7 +337,7 @@ TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncGoodParent) {
// let x: f32 = (*p)[idx];
// 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* star_p = Deref(p);
auto* acc = IndexAccessor(Source{{12, 34}}, star_p, idx);
@ -358,7 +358,7 @@ TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncBadParent) {
// let x: f32 = *p[idx];
// 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* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
auto* star_p = Deref(accessor_expr);

View File

@ -32,7 +32,7 @@ TEST_F(ResolverAssignmentValidationTest, ReadOnlyBuffer) {
auto* s = Structure("S", utils::Vector{
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));
WrapInFunction(Assign(Source{{56, 78}}, MemberAccessor("a", "m"), 1_i));
@ -192,7 +192,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignThroughPointer_Pass) {
// var a : i32;
// let b : ptr<function,i32> = &a;
// *b = 2i;
const auto func = ast::StorageClass::kFunction;
const auto func = ast::AddressSpace::kFunction;
WrapInFunction(Var("a", ty.i32(), func, Expr(2_i)), //
Let("b", ty.pointer<i32>(func), AddressOf(Expr("a"))), //
Assign(Deref("b"), 2_i));
@ -204,7 +204,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignMaterializedThroughPointer_Pass)
// var a : i32;
// let b : ptr<function,i32> = &a;
// *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_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("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{
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));
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{
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));
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{
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")));
@ -310,7 +310,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_DynamicArray_Fail) {
auto* s = Structure("S", utils::Vector{
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")));
@ -363,9 +363,9 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_Pass) {
GlobalVar("tex", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()), Group(0_a),
Binding(0_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("s", ty.Of(S), ast::StorageClass::kStorage, Group(0_a), Binding(3_a));
GlobalVar("wg", ty.array<f32, 10>(), ast::StorageClass::kWorkgroup);
GlobalVar("u", ty.Of(U), ast::AddressSpace::kUniform, Group(0_a), Binding(2_a));
GlobalVar("s", ty.Of(S), ast::AddressSpace::kStorage, Group(0_a), Binding(3_a));
GlobalVar("wg", ty.array<f32, 10>(), ast::AddressSpace::kWorkgroup);
WrapInFunction(Assign(Phony(), 1_i), //
Assign(Phony(), 2_u), //

View File

@ -27,7 +27,7 @@ using namespace tint::number_suffixes; // NOLINT
struct ResolverAtomicTest : public resolver::TestHelper, public testing::Test {};
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();
ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
@ -37,7 +37,7 @@ TEST_F(ResolverAtomicTest, GlobalWorkgroupI32) {
}
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();
ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
@ -48,7 +48,7 @@ TEST_F(ResolverAtomicTest, GlobalWorkgroupU32) {
TEST_F(ResolverAtomicTest, GlobalStorageStruct) {
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));
EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -26,64 +26,64 @@ namespace {
struct ResolverAtomicValidationTest : public resolver::TestHelper, public testing::Test {};
TEST_F(ResolverAtomicValidationTest, StorageClass_WorkGroup) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kWorkgroup);
TEST_F(ResolverAtomicValidationTest, AddressSpace_WorkGroup) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve());
}
TEST_F(ResolverAtomicValidationTest, StorageClass_Storage) {
GlobalVar("g", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kStorage,
TEST_F(ResolverAtomicValidationTest, AddressSpace_Storage) {
GlobalVar("g", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kStorage,
ast::Access::kReadWrite, Group(0_a), Binding(0_a));
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()))});
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));
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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_EQ(r()->error(), "12:34 error: atomic only supports i32 or u32 types");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Simple) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kPrivate);
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Simple) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: atomic variables must have <storage> or <workgroup> "
"storage class");
"address space");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Array) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::StorageClass::kPrivate);
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Array) {
GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"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()))});
GlobalVar("g", ty.Of(s), ast::StorageClass::kPrivate);
GlobalVar("g", ty.Of(s), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> "
"storage class\n"
"address space\n"
"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 Outer { m : array<Inner, 4>; };
// var<private> g : Outer;
@ -91,16 +91,16 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStruct) {
auto* Inner =
Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))});
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_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> "
"storage class\n"
"address space\n"
"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 Outer { m : array<Inner, 4>; };
// var<private> g : Outer;
@ -108,46 +108,46 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_StructOfStructOfArray)
auto* Inner =
Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))});
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_EQ(r()->error(),
"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");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfArray) {
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfArray) {
// type AtomicArray = array<atomic<i32>, 5>;
// var<private> v: array<s, 5>;
auto* atomic_array =
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_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> "
"storage class");
"address space");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStruct) {
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfStruct) {
// struct S{
// m: atomic<u32>;
// };
// var<private> v: array<S, 5u>;
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_EQ(r()->error(),
"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");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStructOfArray) {
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_ArrayOfStructOfArray) {
// type AtomicArray = array<atomic<i32>, 5u>;
// struct S{
// m: AtomicArray;
@ -157,16 +157,16 @@ TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_ArrayOfStructOfArray) {
auto* atomic_array =
Alias(Source{{12, 34}}, "AtomicArray", ty.atomic(Source{{12, 34}}, ty.i32()));
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_EQ(r()->error(),
"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");
}
TEST_F(ResolverAtomicValidationTest, InvalidStorageClass_Complex) {
TEST_F(ResolverAtomicValidationTest, InvalidAddressSpace_Complex) {
// type AtomicArray = array<atomic<i32>, 5u>;
// struct S6 { x: array<i32, 4>; };
// 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* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))});
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_EQ(r()->error(),
"error: atomic variables must have <storage> or <workgroup> "
"storage class\n"
"address space\n"
"note: atomic sub-type of 'S0' is declared here");
}
TEST_F(ResolverAtomicValidationTest, Struct_AccessMode_Read) {
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));
EXPECT_FALSE(r()->Resolve());
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"
"note: atomic sub-type of 's' is declared here");
}
TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_Struct) {
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));
EXPECT_FALSE(r()->Resolve());
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"
"note: atomic sub-type of 's' is declared here");
}
@ -239,12 +239,12 @@ TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_StructOfStruct) {
auto* Inner =
Structure("Inner", utils::Vector{Member("m", ty.atomic(Source{{12, 34}}, ty.i32()))});
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));
EXPECT_FALSE(r()->Resolve());
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"
"note: atomic sub-type of 'Outer' is declared here");
}
@ -257,12 +257,12 @@ TEST_F(ResolverAtomicValidationTest, InvalidAccessMode_StructOfStructOfArray) {
auto* Inner =
Structure("Inner", utils::Vector{Member(Source{{12, 34}}, "m", ty.atomic(ty.i32()))});
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));
EXPECT_FALSE(r()->Resolve());
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"
"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* s1 = Structure("S1", utils::Vector{Member("x", ty.Of(s2))});
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));
EXPECT_FALSE(r()->Resolve());
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"
"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) {
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));
Structure(Source{{6, 4}}, "mystruct",
@ -785,7 +785,7 @@ TEST_P(VariableAttributeTest, IsValid) {
if (IsBindingAttribute(params.kind)) {
GlobalVar("a", ty.sampler(ast::SamplerKind::kSampler), attrs);
} else {
GlobalVar("a", ty.f32(), ast::StorageClass::kPrivate, attrs);
GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate, attrs);
}
if (params.should_pass) {
@ -956,7 +956,7 @@ TEST_P(ArrayStrideTest, All) {
create<ast::StrideAttribute>(Source{{12, 34}}, params.stride),
});
GlobalVar("myarray", arr, ast::StorageClass::kPrivate);
GlobalVar("myarray", arr, ast::AddressSpace::kPrivate);
if (params.should_pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -1039,7 +1039,7 @@ TEST_F(ArrayStrideTest, DuplicateAttribute) {
create<ast::StrideAttribute>(Source{{56, 78}}, 4u),
});
GlobalVar("myarray", arr, ast::StorageClass::kPrivate);
GlobalVar("myarray", arr, ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@ -1058,7 +1058,7 @@ TEST_F(ResourceAttributeTest, UniformBufferMissingBinding) {
auto* s = Structure("S", utils::Vector{
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_EQ(r()->error(),
@ -1069,7 +1069,7 @@ TEST_F(ResourceAttributeTest, StorageBufferMissingBinding) {
auto* s = Structure("S", utils::Vector{
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_EQ(r()->error(),
@ -1155,7 +1155,7 @@ TEST_F(ResourceAttributeTest, BindingPointUsedTwiceByDifferentEntryPoints) {
}
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));
EXPECT_FALSE(r()->Resolve());

View File

@ -78,7 +78,7 @@ using ResolverBuiltinTest_BoolMethod = ResolverTestWithParam<std::string>;
TEST_P(ResolverBuiltinTest_BoolMethod, Scalar) {
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");
WrapInFunction(expr);
@ -91,7 +91,7 @@ TEST_P(ResolverBuiltinTest_BoolMethod, Scalar) {
TEST_P(ResolverBuiltinTest_BoolMethod, Vector) {
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");
WrapInFunction(expr);
@ -106,9 +106,9 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
testing::Values("any", "all"));
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");
WrapInFunction(expr);
@ -212,7 +212,7 @@ using ResolverBuiltinArrayTest = ResolverTest;
TEST_F(ResolverBuiltinArrayTest, ArrayLength_Vector) {
auto* ary = ty.array<i32>();
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));
auto* call = Call("arrayLength", AddressOf(MemberAccessor("a", "x")));
@ -225,7 +225,7 @@ TEST_F(ResolverBuiltinArrayTest, ArrayLength_Vector) {
}
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"));
WrapInFunction(call);
@ -1029,7 +1029,7 @@ TEST_F(ResolverBuiltinFloatTest, FrexpVector_f16) {
}
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"));
WrapInFunction(call);
@ -1045,7 +1045,7 @@ TEST_F(ResolverBuiltinFloatTest, Frexp_Error_FirstParamInt) {
}
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"));
WrapInFunction(call);
@ -1075,7 +1075,7 @@ TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamNotAPointer) {
}
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"));
WrapInFunction(call);
@ -1324,7 +1324,7 @@ TEST_F(ResolverBuiltinFloatTest, ModfVector_f16) {
}
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"));
WrapInFunction(call);
@ -1340,7 +1340,7 @@ TEST_F(ResolverBuiltinFloatTest, Modf_Error_FirstParamInt) {
}
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"));
WrapInFunction(call);
@ -1370,7 +1370,7 @@ TEST_F(ResolverBuiltinFloatTest, Modf_Error_SecondParamNotAPointer) {
}
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"));
WrapInFunction(call);
@ -1850,7 +1850,7 @@ INSTANTIATE_TEST_SUITE_P(
namespace matrix_builtin_tests {
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");
WrapInFunction(call);
@ -1864,7 +1864,7 @@ TEST_F(ResolverBuiltinTest, Determinant_2x2_f32) {
TEST_F(ResolverBuiltinTest, Determinant_2x2_f16) {
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");
WrapInFunction(call);
@ -1876,7 +1876,7 @@ TEST_F(ResolverBuiltinTest, Determinant_2x2_f16) {
}
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");
WrapInFunction(call);
@ -1890,7 +1890,7 @@ TEST_F(ResolverBuiltinTest, Determinant_3x3_f32) {
TEST_F(ResolverBuiltinTest, Determinant_3x3_f16) {
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");
WrapInFunction(call);
@ -1902,7 +1902,7 @@ TEST_F(ResolverBuiltinTest, Determinant_3x3_f16) {
}
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");
WrapInFunction(call);
@ -1916,7 +1916,7 @@ TEST_F(ResolverBuiltinTest, Determinant_4x4_f32) {
TEST_F(ResolverBuiltinTest, Determinant_4x4_f16) {
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");
WrapInFunction(call);
@ -1928,7 +1928,7 @@ TEST_F(ResolverBuiltinTest, Determinant_4x4_f16) {
}
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");
WrapInFunction(call);
@ -1943,7 +1943,7 @@ TEST_F(ResolverBuiltinTest, Determinant_NotSquare) {
}
TEST_F(ResolverBuiltinTest, Determinant_NotMatrix) {
GlobalVar("var", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("var", ty.f32(), ast::AddressSpace::kPrivate);
auto* call = Call("determinant", "var");
WrapInFunction(call);
@ -1963,7 +1963,7 @@ TEST_F(ResolverBuiltinTest, Determinant_NotMatrix) {
namespace vector_builtin_tests {
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");
WrapInFunction(expr);
@ -1977,7 +1977,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec2_f32) {
TEST_F(ResolverBuiltinTest, Dot_Vec2_f16) {
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");
WrapInFunction(expr);
@ -1989,7 +1989,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec2_f16) {
}
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");
WrapInFunction(expr);
@ -2001,7 +2001,7 @@ TEST_F(ResolverBuiltinTest, Dot_Vec3_i32) {
}
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");
WrapInFunction(expr);
@ -2036,7 +2036,7 @@ using ResolverBuiltinDerivativeTest = ResolverTestWithParam<std::string>;
TEST_P(ResolverBuiltinDerivativeTest, Scalar) {
auto name = GetParam();
GlobalVar("ident", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("ident", ty.f32(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "ident");
Func("func", utils::Empty, ty.void_(), utils::Vector{Ignore(expr)},
@ -2050,7 +2050,7 @@ TEST_P(ResolverBuiltinDerivativeTest, Scalar) {
TEST_P(ResolverBuiltinDerivativeTest, Vector) {
auto name = GetParam();
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate);
GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* expr = Call(name, "ident");
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));
} else {
GlobalVar(name, type, ast::StorageClass::kPrivate);
GlobalVar(name, type, ast::AddressSpace::kPrivate);
}
call_params->Push(Expr(name));

View File

@ -113,7 +113,7 @@ TEST_F(ResolverBuiltinValidationTest, BuiltinRedeclaredAsGlobalConst) {
}
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_EQ(

View File

@ -100,7 +100,7 @@ using ResolverBuiltinsStageTest = ResolverTestWithParam<Params>;
TEST_P(ResolverBuiltinsStageTest, All_input) {
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),
utils::Vector{Builtin(Source{{12, 34}}, params.builtin)});
switch (params.stage) {

View File

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

View File

@ -51,7 +51,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, CompatibleTypesAssignThroughPoi
// var a : i32;
// let b : ptr<function,i32> = &a;
// *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_b = Let("b", ty.pointer<i32>(func), AddressOf(Expr("a")));
WrapInFunction(var_a, var_b,
@ -233,7 +233,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, ReadOnlyBuffer) {
// {
// 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));
WrapInFunction(CompoundAssign(Source{{56, 78}}, "a", 1_i, ast::BinaryOp::kAdd));
@ -264,7 +264,7 @@ TEST_F(ResolverCompoundAssignmentValidationTest, LhsLiteral) {
TEST_F(ResolverCompoundAssignmentValidationTest, LhsAtomic) {
// 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(CompoundAssign(Source{{56, 78}}, "a", "a", ast::BinaryOp::kAdd));
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) {
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));
WrapInFunction(expr);

View File

@ -425,7 +425,7 @@ const ast::Node* SymbolTestHelper::Add(SymbolDeclKind kind, Symbol symbol, Sourc
auto& b = *builder;
switch (kind) {
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:
return b.GlobalConst(source, symbol, b.ty.i32(), b.Expr(1_i));
case SymbolDeclKind::Alias:
@ -468,27 +468,27 @@ const ast::Node* SymbolTestHelper::Add(SymbolUseKind kind, Symbol symbol, Source
switch (kind) {
case SymbolUseKind::GlobalVarType: {
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;
}
case SymbolUseKind::GlobalVarArrayElemType: {
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;
}
case SymbolUseKind::GlobalVarArraySizeValue: {
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;
}
case SymbolUseKind::GlobalVarVectorElemType: {
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;
}
case SymbolUseKind::GlobalVarMatrixElemType: {
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;
}
case SymbolUseKind::GlobalVarSampledTexElemType: {
@ -503,7 +503,7 @@ const ast::Node* SymbolTestHelper::Add(SymbolUseKind kind, Symbol symbol, Source
}
case SymbolUseKind::GlobalVarValue: {
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;
}
case SymbolUseKind::GlobalConstType: {
@ -724,7 +724,7 @@ TEST_F(ResolverDependencyGraphUsedBeforeDeclTest, VarUsed) {
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();
}
@ -1207,7 +1207,7 @@ TEST_F(ResolverDependencyGraphTraversalTest, SymbolsReached) {
const auto type_sym = Sym("TYPE");
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* 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.vec3(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.depth_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;
// var<push_constant> a : u32;
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant);
EXPECT_TRUE(r()->Resolve());
}
TEST_F(ResolverEntryPointValidationTest, PushConstantDisallowedWithoutEnable) {
// 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_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'");
}
TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithIgnoreStorageClassAttribute) {
// var<push_constant> a : u32; // With ast::DisabledValidation::kIgnoreStorageClass
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant,
utils::Vector{Disable(ast::DisabledValidation::kIgnoreStorageClass)});
TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithIgnoreAddressSpaceAttribute) {
// var<push_constant> a : u32; // With ast::DisabledValidation::kIgnoreAddressSpace
GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant,
utils::Vector{Disable(ast::DisabledValidation::kIgnoreAddressSpace)});
EXPECT_TRUE(r()->Resolve());
}
@ -483,7 +483,7 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantOneVariableUsedInEntryPoint
// _ = a;
// }
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")},
utils::Vector{Stage(ast::PipelineStage::kCompute),
@ -501,8 +501,8 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInEntryPoin
// _ = b;
// }
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::AddressSpace::kPushConstant);
GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::AddressSpace::kPushConstant);
Func(Source{{5, 6}}, "main", {}, ty.void_(),
utils::Vector{Assign(Phony(), "a"), Assign(Phony(), "b")},
@ -532,8 +532,8 @@ TEST_F(ResolverEntryPointValidationTest,
// uses_b();
// }
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar(Source{{3, 4}}, "b", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar(Source{{1, 2}}, "a", ty.u32(), ast::AddressSpace::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{{7, 8}}, "uses_b", {}, ty.void_(), utils::Vector{Assign(Phony(), "b")});
@ -565,8 +565,8 @@ TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInDifferent
// _ = a;
// }
Enable(ast::Extension::kChromiumExperimentalPushConstant);
GlobalVar("a", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar("b", ty.u32(), ast::StorageClass::kPushConstant);
GlobalVar("a", ty.u32(), ast::AddressSpace::kPushConstant);
GlobalVar("b", ty.u32(), ast::AddressSpace::kPushConstant);
Func("uses_a", {}, ty.void_(), utils::Vector{Assign(Phony(), "a")},
utils::Vector{Stage(ast::PipelineStage::kCompute),

View File

@ -39,7 +39,7 @@ TEST_F(ResolverFunctionValidationTest, DuplicateParameterName) {
TEST_F(ResolverFunctionValidationTest, ParameterMayShadowGlobal) {
// var<private> 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);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -388,7 +388,7 @@ TEST_F(ResolverFunctionValidationTest, CannotCallFunctionAtModuleScope) {
utils::Vector{
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_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;
// @compute @workgroup_size(x)
// 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,
utils::Vector{
Stage(ast::PipelineStage::kCompute),
@ -830,7 +830,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_InvalidExpr_z) {
}
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);
EXPECT_FALSE(r()->Resolve());
@ -939,16 +939,16 @@ TEST_F(ResolverFunctionValidationTest, ParameterMatrixNoType) {
}
struct TestParams {
ast::StorageClass storage_class;
ast::AddressSpace address_space;
bool should_pass;
};
struct TestWithParams : ResolverTestWithParam<TestParams> {};
using ResolverFunctionParameterValidationTest = TestWithParams;
TEST_P(ResolverFunctionParameterValidationTest, StorageClass) {
TEST_P(ResolverFunctionParameterValidationTest, AddressSpace) {
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);
Func("f", utils::Vector{arg}, ty.void_(), utils::Empty);
@ -956,23 +956,23 @@ TEST_P(ResolverFunctionParameterValidationTest, StorageClass) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
} else {
std::stringstream ss;
ss << param.storage_class;
ss << param.address_space;
EXPECT_FALSE(r()->Resolve());
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,
ResolverFunctionParameterValidationTest,
testing::Values(TestParams{ast::StorageClass::kNone, false},
TestParams{ast::StorageClass::kIn, false},
TestParams{ast::StorageClass::kOut, false},
TestParams{ast::StorageClass::kUniform, false},
TestParams{ast::StorageClass::kWorkgroup, true},
TestParams{ast::StorageClass::kHandle, false},
TestParams{ast::StorageClass::kStorage, false},
TestParams{ast::StorageClass::kPrivate, true},
TestParams{ast::StorageClass::kFunction, true}));
testing::Values(TestParams{ast::AddressSpace::kNone, false},
TestParams{ast::AddressSpace::kIn, false},
TestParams{ast::AddressSpace::kOut, false},
TestParams{ast::AddressSpace::kUniform, false},
TestParams{ast::AddressSpace::kWorkgroup, true},
TestParams{ast::AddressSpace::kHandle, false},
TestParams{ast::AddressSpace::kStorage, false},
TestParams{ast::AddressSpace::kPrivate, true},
TestParams{ast::AddressSpace::kFunction, true}));
} // namespace
} // namespace tint::resolver

View File

@ -28,14 +28,14 @@ using ResolverHostShareableValidationTest = ResolverTest;
TEST_F(ResolverHostShareableValidationTest, BoolMember) {
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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
56:78 note: while instantiating 'var' g)");
}
@ -43,14 +43,14 @@ TEST_F(ResolverHostShareableValidationTest, BoolMember) {
TEST_F(ResolverHostShareableValidationTest, BoolVectorMember) {
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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
56:78 note: while instantiating 'var' g)");
}
@ -59,14 +59,14 @@ TEST_F(ResolverHostShareableValidationTest, Aliases) {
auto* a1 = Alias("a1", ty.bool_());
auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.Of(a1))});
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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
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))});
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));
ASSERT_FALSE(r()->Resolve());
EXPECT_EQ(
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
3:4 note: while analysing structure member I2.y
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))});
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();

View File

@ -64,8 +64,8 @@ TEST_F(ResolverIncrementDecrementValidationTest, ThroughPointer) {
// var a : i32;
// let b : ptr<function,i32> = &a;
// *b++;
auto* var_a = Var("a", ty.i32(), ast::StorageClass::kFunction);
auto* var_b = Let("b", ty.pointer<i32>(ast::StorageClass::kFunction), AddressOf(Expr("a")));
auto* var_a = Var("a", ty.i32(), ast::AddressSpace::kFunction);
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")));
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -127,7 +127,7 @@ TEST_F(ResolverIncrementDecrementValidationTest, Vector) {
TEST_F(ResolverIncrementDecrementValidationTest, Atomic) {
// var<workgroup> a : atomic<i32>;
// 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")));
EXPECT_FALSE(r()->Resolve());
@ -193,7 +193,7 @@ TEST_F(ResolverIncrementDecrementValidationTest, ReadOnlyBuffer) {
// {
// 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));
WrapInFunction(Increment(Source{{56, 78}}, "a"));

View File

@ -97,7 +97,7 @@ TEST_P(ResolverInferredTypeParamTest, GlobalVar_Pass) {
// var a = <type constructor>;
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_EQ(TypeOf(var)->UnwrapRef(), expected_type);
@ -124,7 +124,7 @@ TEST_P(ResolverInferredTypeParamTest, LocalVar_Pass) {
// var a = <type constructor>;
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);
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);
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -158,7 +158,7 @@ TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();

View File

@ -321,7 +321,7 @@ class TemplateNumberMatcher : public NumberMatcher {
////////////////////////////////////////////////////////////////////////////////
using TexelFormat = ast::TexelFormat;
using Access = ast::Access;
using StorageClass = ast::StorageClass;
using AddressSpace = ast::AddressSpace;
using ParameterUsage = sem::ParameterUsage;
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>()) {
S = Number(static_cast<uint32_t>(p->StorageClass()));
S = Number(static_cast<uint32_t>(p->AddressSpace()));
T = p->StoreType();
A = Number(static_cast<uint32_t>(p->Access()));
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) {
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()));
}
@ -1158,7 +1158,7 @@ Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
params.Reserve(match.parameters.Length());
for (auto& p : match.parameters) {
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));
}
sem::PipelineStageSet supported_stages;
@ -1356,7 +1356,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
params.Reserve(match.parameters.Length());
for (auto& p : match.parameters) {
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));
}
auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
@ -1371,7 +1371,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
// Conversion.
auto* target = utils::GetOrCreate(converters, match, [&]() {
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);
auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
: sem::EvaluationStage::kRuntime;

View File

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

View File

@ -216,7 +216,7 @@ TEST_F(IntrinsicTableTest, MatchPointer) {
auto* i32 = create<sem::I32>();
auto* atomicI32 = create<sem::Atomic>(i32);
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{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
@ -236,7 +236,7 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
TEST_F(IntrinsicTableTest, MatchArray) {
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{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
ASSERT_EQ(Diagnostics().str(), "");
@ -424,7 +424,7 @@ TEST_F(IntrinsicTableTest, ImplicitLoadOnReference) {
auto result = table->Lookup(
BuiltinType::kCos,
utils::Vector{
create<sem::Reference>(f32, ast::StorageClass::kFunction, ast::Access::kReadWrite),
create<sem::Reference>(f32, ast::AddressSpace::kFunction, ast::Access::kReadWrite),
},
Source{});
ASSERT_NE(result.sem, nullptr) << Diagnostics().str();

View File

@ -95,7 +95,7 @@ TEST_F(ResolverIsHostShareable, Matrix) {
}
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);
EXPECT_FALSE(r()->IsHostShareable(ptr));
}

View File

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

View File

@ -902,7 +902,7 @@ TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
utils::Vector{WorkgroupSize(abstract_expr()), Stage(ast::PipelineStage::kCompute)});
break;
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()));
break;
case Method::kRuntimeIndex:

View File

@ -38,7 +38,7 @@ TEST_F(ResolverPtrRefTest, AddressOf) {
ASSERT_TRUE(TypeOf(expr)->Is<sem::Pointer>());
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) {
@ -56,28 +56,28 @@ TEST_F(ResolverPtrRefTest, AddressOfThenDeref) {
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
auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())});
auto* function = Var("f", ty.i32());
auto* private_ = GlobalVar("p", ty.i32(), ast::StorageClass::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::StorageClass::kWorkgroup);
auto* private_ = GlobalVar("p", ty.i32(), ast::AddressSpace::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::AddressSpace::kWorkgroup);
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 =
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 =
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 =
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 =
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 =
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 =
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);

View File

@ -62,7 +62,7 @@ TEST_F(ResolverPtrRefValidationTest, AddressOfHandle) {
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: cannot take the address of expression in handle "
"storage class");
"address space");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_MemberAccessor) {
@ -102,7 +102,7 @@ TEST_F(ResolverPtrRefValidationTest, IndirectOfAddressOfHandle) {
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: cannot take the address of expression in handle "
"storage class");
"address space");
}
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* 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));
auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 2_i);
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);

View File

@ -247,9 +247,9 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
if (auto* el = Type(t->type)) {
auto access = t->access;
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;
},
@ -368,11 +368,11 @@ sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
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;
}
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty),
if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
v->source)) {
AddNote("while instantiating 'let' " + builder_->Symbols().NameFor(v->symbol), v->source);
return nullptr;
@ -381,12 +381,12 @@ sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
sem::Variable* sem = nullptr;
if (is_global) {
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{},
std::nullopt);
} else {
sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime,
ast::StorageClass::kNone,
ast::AddressSpace::kNone,
ast::Access::kUndefined, current_statement_,
/* constant_value */ nullptr);
}
@ -425,11 +425,11 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
return nullptr;
}
if (rhs && !validator_.VariableInitializer(v, ast::StorageClass::kNone, ty, rhs)) {
if (rhs && !validator_.VariableInitializer(v, ast::AddressSpace::kNone, ty, rhs)) {
return nullptr;
}
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty),
if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
v->source)) {
AddNote("while instantiating 'override' " + builder_->Symbols().NameFor(v->symbol),
v->source);
@ -437,7 +437,7 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
}
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);
sem->SetConstructor(rhs);
@ -510,21 +510,21 @@ sem::Variable* Resolver::Const(const ast::Const* c, bool is_global) {
return nullptr;
}
if (!validator_.VariableInitializer(c, ast::StorageClass::kNone, ty, rhs)) {
if (!validator_.VariableInitializer(c, ast::AddressSpace::kNone, ty, rhs)) {
return nullptr;
}
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, const_cast<sem::Type*>(ty),
if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, const_cast<sem::Type*>(ty),
c->source)) {
AddNote("while instantiating 'const' " + builder_->Symbols().NameFor(c->symbol), c->source);
return nullptr;
}
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))
: 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));
sem->SetConstructor(rhs);
@ -562,39 +562,39 @@ sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
return nullptr;
}
auto storage_class = var->declared_storage_class;
if (storage_class == ast::StorageClass::kNone) {
// No declared storage class. Infer from usage / type.
auto address_space = var->declared_address_space;
if (address_space == ast::AddressSpace::kNone) {
// No declared address space. Infer from usage / type.
if (!is_global) {
storage_class = ast::StorageClass::kFunction;
address_space = ast::AddressSpace::kFunction;
} else if (storage_ty->UnwrapRef()->is_handle()) {
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the
// variable declaration must not have a storage class attribute. The
// storage class will always be handle.
storage_class = ast::StorageClass::kHandle;
// variable declaration must not have a address space attribute. The
// address space will always be handle.
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,
ast::DisabledValidation::kIgnoreStorageClass)) {
AddError("function-scope 'var' declaration must use 'function' storage class", var->source);
ast::DisabledValidation::kIgnoreAddressSpace)) {
AddError("function-scope 'var' declaration must use 'function' address space", var->source);
return nullptr;
}
auto access = var->declared_access;
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;
}
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),
var->source);
return nullptr;
@ -654,12 +654,12 @@ sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
}
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);
} else {
sem = builder_->create<sem::LocalVariable>(var, var_ty, sem::EvaluationStage::kRuntime,
storage_class, access, current_statement_,
address_space, access, current_statement_,
/* constant_value */ nullptr);
}
@ -686,7 +686,7 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
return nullptr;
}
if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, ty, param->source)) {
if (!ApplyAddressSpaceUsageToType(ast::AddressSpace::kNone, ty, param->source)) {
add_note();
return nullptr;
}
@ -694,8 +694,8 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
if (auto* ptr = ty->As<sem::Pointer>()) {
// For MSL, we push module-scope variables into the entry point as pointer
// parameters, so we also need to handle their store type.
if (!ApplyStorageClassUsageToType(
ptr->StorageClass(), const_cast<sem::Type*>(ptr->StoreType()), param->source)) {
if (!ApplyAddressSpaceUsageToType(
ptr->AddressSpace(), const_cast<sem::Type*>(ptr->StoreType()), param->source)) {
add_note();
return nullptr;
}
@ -749,18 +749,18 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
}
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);
builder_->Sem().Add(param, 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
switch (storage_class) {
case ast::StorageClass::kStorage:
case ast::StorageClass::kUniform:
case ast::StorageClass::kHandle:
switch (address_space) {
case ast::AddressSpace::kStorage:
case ast::AddressSpace::kUniform:
case ast::AddressSpace::kHandle:
return ast::Access::kRead;
default:
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
// referenced structs
if (!validator_.StorageClassLayout(sem, enabled_extensions_, valid_type_storage_layouts_)) {
if (!validator_.AddressSpaceLayout(sem, enabled_extensions_, valid_type_storage_layouts_)) {
return nullptr;
}
@ -962,7 +962,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
}
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(
"while instantiating return type for " + builder_->Symbols().NameFor(decl->symbol),
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 (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());
@ -1783,7 +1783,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
nullptr, // declaration
static_cast<uint32_t>(i), // index
arr->ElemType(), // type
ast::StorageClass::kNone, // storage_class
ast::AddressSpace::kNone, // address_space
ast::Access::kUndefined);
});
return builder_->create<sem::TypeConstructor>(arr, std::move(params),
@ -1812,7 +1812,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
nullptr, // declaration
static_cast<uint32_t>(i), // index
str->Members()[i]->Type(), // type
ast::StorageClass::kNone, // storage_class
ast::AddressSpace::kNone, // address_space
ast::Access::kUndefined); // access
}
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 (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);
@ -2390,7 +2390,7 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
ty = vec->type();
// If we're extracting from a reference, we return a 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 {
// 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:
if (auto* ref = expr_ty->As<sem::Reference>()) {
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);
return nullptr;
}
@ -2496,7 +2496,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
return nullptr;
}
ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->StorageClass(),
ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(),
ref->Access());
source_var = expr->SourceVariable();
@ -2508,7 +2508,7 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
case ast::UnaryOp::kIndirection:
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());
source_var = expr->SourceVariable();
} else {
@ -3205,20 +3205,20 @@ sem::Statement* Resolver::IncrementDecrementStatement(
});
}
bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc,
bool Resolver::ApplyAddressSpaceUsageToType(ast::AddressSpace sc,
sem::Type* ty,
const Source& usage) {
ty = const_cast<sem::Type*>(ty->UnwrapRef());
if (auto* str = ty->As<sem::Struct>()) {
if (str->StorageClassUsage().count(sc)) {
if (str->AddressSpaceUsage().count(sc)) {
return true; // Already applied
}
str->AddUsage(sc);
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;
err << "while analysing structure member " << sem_.TypeNameOf(str) << "."
<< builder_->Symbols().NameFor(member->Declaration()->symbol);
@ -3230,20 +3230,20 @@ bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc,
}
if (auto* arr = ty->As<sem::Array>()) {
if (arr->IsRuntimeSized() && sc != ast::StorageClass::kStorage) {
if (arr->IsRuntimeSized() && sc != ast::AddressSpace::kStorage) {
AddError(
"runtime-sized arrays can only be used in the <storage> storage "
"class",
"runtime-sized arrays can only be used in the <storage> address "
"space",
usage);
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)) {
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";
AddError(err.str(), usage);
return false;

View File

@ -387,20 +387,20 @@ class Resolver {
/// @param index the index of the parameter
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
/// given storage class, erroring if it cannot.
/// @param sc the storage class to apply to the type and transitent types
/// @param ty the type to apply the storage class on
/// given address space, erroring if it cannot.
/// @param sc the address space to apply to the type and transitent types
/// @param ty the type to apply the address space on
/// @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.
/// @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
/// @returns the default access control for the given storage class
ast::Access DefaultAccessForStorageClass(ast::StorageClass storage_class);
/// @param address_space the address space
/// @returns the default access control for the given address space
ast::Access DefaultAccessForAddressSpace(ast::AddressSpace address_space);
/// Allocate constant IDs for pipeline-overridable constants.
/// @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) {
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();
@ -396,7 +396,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
Func("func_i32", utils::Empty, ty.void_(), utils::Vector{fn_i32_decl});
// 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;
AST().AddGlobalVariable(mod_f32);
@ -424,7 +424,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
// 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();
@ -437,7 +437,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
TEST_F(ResolverTest, ArraySize_SignedLiteral) {
// 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();
@ -452,7 +452,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedConst) {
// const size = 10u;
// var<private> a : array<f32, size>;
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();
@ -467,7 +467,7 @@ TEST_F(ResolverTest, ArraySize_SignedConst) {
// const size = 0;
// var<private> a : array<f32, size>;
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();
@ -482,7 +482,7 @@ TEST_F(ResolverTest, ArraySize_Override) {
// override size = 0;
// var<workgroup> a : array<f32, size>;
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();
@ -500,8 +500,8 @@ TEST_F(ResolverTest, ArraySize_Override_Equivalence) {
// var<workgroup> a : array<f32, size>;
// var<workgroup> b : array<f32, size>;
auto* override = Override("size", Expr(10_i));
auto* a = GlobalVar("a", ty.array(ty.f32(), Expr("size")), ast::StorageClass::kWorkgroup);
auto* b = GlobalVar("b", 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::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -523,7 +523,7 @@ TEST_F(ResolverTest, ArraySize_Override_Equivalence) {
}
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"));
WrapInFunction(bitcast);
@ -586,7 +586,7 @@ TEST_F(ResolverTest, Expr_Call_Builtin) {
}
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");
WrapInFunction(cast);
@ -644,7 +644,7 @@ TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) {
}
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");
WrapInFunction(ident);
@ -747,7 +747,7 @@ TEST_F(ResolverTest, Expr_Identifier_Function_Ptr) {
auto* v = Expr("v");
auto* p = Expr("p");
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);
Func("my_func", utils::Empty, ty.void_(),
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_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",
utils::Vector{
param_a,
@ -852,8 +852,8 @@ TEST_F(ResolverTest, Function_Parameters_Locations) {
TEST_F(ResolverTest, Function_GlobalVariable_Location) {
auto* var = GlobalVar(
"my_vec", ty.vec4<f32>(), ast::StorageClass::kIn,
utils::Vector{Location(3_a), Disable(ast::DisabledValidation::kIgnoreStorageClass)});
"my_vec", ty.vec4<f32>(), ast::AddressSpace::kIn,
utils::Vector{Location(3_a), Disable(ast::DisabledValidation::kIgnoreAddressSpace)});
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -865,10 +865,10 @@ TEST_F(ResolverTest, Function_GlobalVariable_Location) {
TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
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));
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::StorageClass::kPrivate);
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::AddressSpace::kPrivate);
auto* func = Func("my_func", utils::Empty, ty.void_(),
utils::Vector{
@ -911,7 +911,7 @@ TEST_F(ResolverTest, Function_ReturnType_Location) {
}
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>(),
utils::Vector{
Return("my_vec"),
@ -933,10 +933,10 @@ TEST_F(ResolverTest, Function_ReturnType_NoLocation) {
TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) {
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));
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::StorageClass::kPrivate);
auto* wg_var = GlobalVar("wg_var", ty.f32(), ast::AddressSpace::kWorkgroup);
auto* priv_var = GlobalVar("priv_var", ty.f32(), ast::AddressSpace::kPrivate);
Func("my_func", utils::Empty, ty.f32(),
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) {
auto* st = Structure(
"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");
WrapInFunction(mem);
@ -1211,7 +1211,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
auto* st = Structure(
"S", utils::Vector{Member("first_member", ty.i32()), Member("second_member", ty.f32())});
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");
WrapInFunction(mem);
@ -1231,7 +1231,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
}
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");
WrapInFunction(mem);
@ -1249,7 +1249,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
}
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");
WrapInFunction(mem);
@ -1285,7 +1285,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
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))});
GlobalVar("c", ty.Of(stA), ast::StorageClass::kPrivate);
GlobalVar("c", ty.Of(stA), ast::AddressSpace::kPrivate);
auto* mem =
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) {
auto* st = Structure(
"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"),
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);
SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate);
GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr);
@ -1641,8 +1641,8 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) {
<< FriendlyName(rhs_type);
SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate);
GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr);
@ -1687,8 +1687,8 @@ TEST_P(Expr_Binary_Test_Invalid, All) {
ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type);
SCOPED_TRACE(ss.str());
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate);
GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, op, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr);
@ -1727,8 +1727,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) {
is_valid_expr = vec_size == mat_cols;
}
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate);
GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr);
@ -1764,8 +1764,8 @@ TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) {
auto* col = create<sem::Vector>(f32, lhs_mat_rows);
auto* result_type = create<sem::Matrix>(col, rhs_mat_cols);
GlobalVar("lhs", lhs_type, ast::StorageClass::kPrivate);
GlobalVar("rhs", rhs_type, ast::StorageClass::kPrivate);
GlobalVar("lhs", lhs_type, ast::AddressSpace::kPrivate);
GlobalVar("rhs", rhs_type, ast::AddressSpace::kPrivate);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr);
@ -1793,11 +1793,11 @@ TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
auto op = GetParam();
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) {
GlobalVar("ident", ty.vec4<i32>(), ast::StorageClass::kPrivate);
GlobalVar("ident", ty.vec4<i32>(), ast::AddressSpace::kPrivate);
} 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"));
WrapInFunction(der);
@ -1821,7 +1821,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
ast::UnaryOp::kNegation,
ast::UnaryOp::kNot));
TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
TEST_F(ResolverTest, AddressSpace_SetsIfMissing) {
auto* var = Var("var", ty.i32());
auto* stmt = Decl(var);
@ -1829,42 +1829,42 @@ TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
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* var = GlobalVar("var", t, Binding(0_a), Group(0_a));
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* var = GlobalVar("var", t, Binding(0_a), Group(0_a));
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* stmt = Decl(var);
Func("func", utils::Empty, ty.void_(), utils::Vector{stmt});
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) {
// struct S { x : i32 };
// var<storage> g : S;
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));
EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -1897,11 +1897,11 @@ TEST_F(ResolverTest, Function_EntryPoints_StageAttribute) {
// ep_1 -> {}
// ep_2 -> {}
GlobalVar("first", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("second", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("call_a", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("call_b", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("call_c", ty.f32(), ast::StorageClass::kPrivate);
GlobalVar("first", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("second", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_a", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_b", ty.f32(), ast::AddressSpace::kPrivate);
GlobalVar("call_c", ty.f32(), ast::AddressSpace::kPrivate);
auto* func_b = Func("b", utils::Empty, ty.f32(),
utils::Vector{
@ -2041,8 +2041,8 @@ TEST_F(ResolverTest, ASTNodeReachedTwice) {
{
ProgramBuilder b;
auto* expr = b.Expr(1_i);
b.GlobalVar("a", b.ty.i32(), ast::StorageClass::kPrivate, expr);
b.GlobalVar("b", b.ty.i32(), ast::StorageClass::kPrivate, expr);
b.GlobalVar("a", b.ty.i32(), ast::AddressSpace::kPrivate, expr);
b.GlobalVar("b", b.ty.i32(), ast::AddressSpace::kPrivate, expr);
Resolver(&b).Resolve();
},
"internal compiler error: AST node 'tint::ast::IntLiteralExpression' was encountered twice "
@ -2050,7 +2050,7 @@ TEST_F(ResolverTest, ASTNodeReachedTwice) {
}
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"));
WrapInFunction(der);
@ -2059,7 +2059,7 @@ TEST_F(ResolverTest, UnaryOp_Not) {
}
TEST_F(ResolverTest, UnaryOp_Complement) {
GlobalVar("ident", ty.vec4<f32>(), ast::StorageClass::kPrivate);
GlobalVar("ident", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* der =
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr(Source{{12, 34}}, "ident"));
WrapInFunction(der);
@ -2069,7 +2069,7 @@ TEST_F(ResolverTest, UnaryOp_Complement) {
}
TEST_F(ResolverTest, UnaryOp_Negation) {
GlobalVar("ident", ty.u32(), ast::StorageClass::kPrivate);
GlobalVar("ident", ty.u32(), ast::AddressSpace::kPrivate);
auto* der =
create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation, Expr(Source{{12, 34}}, "ident"));
WrapInFunction(der);
@ -2214,15 +2214,15 @@ TEST_F(ResolverTest, TextureSampler_TextureDimensions) {
TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) {
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* s0 = Structure("s0", utils::Vector{Member("m", ty.i32())});
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* s1 = Structure("s1", utils::Vector{Member("m", ty.i32())});
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* s2 = Structure("s2", utils::Vector{Member("m", ty.i32())});

View File

@ -604,13 +604,13 @@ struct DataType<ptr<T>> {
/// @param b the ProgramBuilder
/// @return a new AST alias type
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);
}
/// @param b the ProgramBuilder
/// @return the semantic aliased type
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);
}
@ -618,7 +618,7 @@ struct DataType<ptr<T>> {
/// @return a new AST expression of the pointer type
static inline const ast::Expression* Expr(ProgramBuilder& b, ScalarArgs /*unused*/) {
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);
}

View File

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

View File

@ -26,7 +26,7 @@ namespace {
class ResolverSourceVariableTest : public ResolverTest {};
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);
WrapInFunction(expr);
@ -37,7 +37,7 @@ TEST_F(ResolverSourceVariableTest, GlobalPrivateVar) {
}
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);
WrapInFunction(expr);
@ -48,7 +48,7 @@ TEST_F(ResolverSourceVariableTest, GlobalWorkgroupVar) {
}
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);
WrapInFunction(expr);
@ -59,7 +59,7 @@ TEST_F(ResolverSourceVariableTest, GlobalStorageVar) {
}
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);
WrapInFunction(expr);
@ -71,7 +71,7 @@ TEST_F(ResolverSourceVariableTest, GlobalUniformVar) {
TEST_F(ResolverSourceVariableTest, GlobalTextureVar) {
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);
WrapInFunction(Call("textureDimensions", expr));
@ -141,7 +141,7 @@ TEST_F(ResolverSourceVariableTest, PointerParameter) {
// {
// 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* let = Let("b", expr_param);
auto* expr_let = Expr("b");
@ -198,7 +198,7 @@ TEST_F(ResolverSourceVariableTest, ThroughIndexAccessor) {
// {
// 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);
WrapInFunction(expr);
@ -215,7 +215,7 @@ TEST_F(ResolverSourceVariableTest, ThroughMemberAccessor) {
// a.f
// }
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");
WrapInFunction(expr);
@ -231,7 +231,7 @@ TEST_F(ResolverSourceVariableTest, ThroughPointers) {
// let a_ptr1 = &*&a;
// 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* deref_1 = Deref(address_of_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) {
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")));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),

View File

@ -25,19 +25,19 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::resolver {
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())});
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>();
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())});
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>();
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())});
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>();
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())});
GlobalVar("g", ty.Of(s), ast::StorageClass::kPrivate);
GlobalVar("g", ty.Of(s), ast::AddressSpace::kPrivate);
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>();
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* 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();
auto* sem = TypeOf(s)->As<sem::Struct>();
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* 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();
auto* sem = TypeOf(s)->As<sem::Struct>();
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* 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();
auto* sem = TypeOf(s)->As<sem::Struct>();
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())});
WrapInFunction(Var("g", ty.Of(s)));
@ -118,10 +118,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableFromLocal) {
auto* sem = TypeOf(s)->As<sem::Struct>();
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* a = Alias("A", ty.Of(s));
WrapInFunction(Var("g", ty.Of(a)));
@ -130,10 +130,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) {
auto* sem = TypeOf(s)->As<sem::Struct>();
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* o = Structure("O", utils::Vector{Member("a", ty.Of(s))});
WrapInFunction(Var("g", ty.Of(o)));
@ -142,10 +142,10 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalStruct) {
auto* sem = TypeOf(s)->As<sem::Struct>();
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* a = ty.array(ty.Of(s), 3_u);
WrapInFunction(Var("g", a));
@ -154,13 +154,13 @@ TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalArray) {
auto* sem = TypeOf(s)->As<sem::Struct>();
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())});
GlobalVar("x", ty.Of(s), ast::StorageClass::kUniform, Binding(0_a), Group(0_a));
GlobalVar("y", ty.Of(s), ast::StorageClass::kStorage, ast::Access::kRead, Binding(1_a),
GlobalVar("x", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
GlobalVar("y", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(1_a),
Group(0_a));
WrapInFunction(Var("g", ty.Of(s)));
@ -168,9 +168,9 @@ TEST_F(ResolverStorageClassUseTest, StructMultipleStorageClassUses) {
auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr);
EXPECT_THAT(sem->StorageClassUsage(),
UnorderedElementsAre(ast::StorageClass::kUniform, ast::StorageClass::kStorage,
ast::StorageClass::kFunction));
EXPECT_THAT(sem->AddressSpaceUsage(),
UnorderedElementsAre(ast::AddressSpace::kUniform, ast::AddressSpace::kStorage,
ast::AddressSpace::kFunction));
}
} // namespace

View File

@ -69,10 +69,10 @@ TEST_F(ResolverTypeConstructorValidationTest, InferTypeTest_Simple) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(a_ident)->Is<sem::Reference>());
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>());
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>;
@ -96,7 +96,7 @@ TEST_P(InferTypeTest_FromConstructorExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident);
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"
<< "expected: " << FriendlyName(expected) << "\n";
}
@ -150,7 +150,7 @@ TEST_P(InferTypeTest_FromArithmeticExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident);
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"
<< "expected: " << FriendlyName(expected) << "\n";
}
@ -198,7 +198,7 @@ TEST_P(InferTypeTest_FromCallExpression, All) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* got = TypeOf(a_ident);
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"
<< "expected: " << FriendlyName(expected) << "\n";
}
@ -1968,7 +1968,7 @@ TEST_F(ResolverTypeConstructorValidationTest, NestedVectorConstructors_Success)
TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) {
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");
WrapInFunction(tc);
@ -1980,8 +1980,8 @@ TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) {
TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Success) {
auto* f32_alias = Alias("Float32", ty.f32());
auto* vec2_alias = Alias("VectorFloat2", ty.vec2<f32>());
GlobalVar("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate);
GlobalVar("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate);
GlobalVar("my_f32", ty.Of(f32_alias), ast::AddressSpace::kPrivate);
GlobalVar("my_vec2", ty.Of(vec2_alias), ast::AddressSpace::kPrivate);
auto* tc = vec3<f32>("my_vec2", "my_f32");
WrapInFunction(tc);

View File

@ -80,14 +80,14 @@ TEST_F(ResolverTypeValidationTest, GlobalOverrideNoConstructor_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, GlobalVariableWithStorageClass_Pass) {
TEST_F(ResolverTypeValidationTest, GlobalVariableWithAddressSpace_Pass) {
// 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();
}
TEST_F(ResolverTypeValidationTest, GlobalConstNoStorageClass_Pass) {
TEST_F(ResolverTypeValidationTest, GlobalConstNoAddressSpace_Pass) {
// const global_const: f32 = 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_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();
}
@ -116,7 +116,7 @@ TEST_F(ResolverTypeValidationTest, GlobalVariableFunctionVariableNotUnique_Pass)
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();
}
@ -180,19 +180,19 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierDifferentFunctions_Pass)
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Pass) {
// 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();
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Pass) {
// 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();
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Pass) {
// 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();
}
@ -200,7 +200,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConst_Pass) {
// const size = 4u;
// var<private> a : array<f32, size>;
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();
}
@ -208,34 +208,34 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConst_Pass) {
// const size = 4i;
// var<private> a : array<f32, size>;
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();
}
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Zero) {
// 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_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Zero) {
// 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_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Zero) {
// 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_EQ(r()->error(), "12:34 error: array size (0) must be greater than 0");
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Negative) {
// 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_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;
// var<private> a : array<f32, size>;
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_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;
// var<private> a : array<f32, size>;
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_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;
// var<private> a : array<f32, size>;
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_EQ(r()->error(), "12:34 error: array size (-10) must be greater than 0");
}
TEST_F(ResolverTypeValidationTest, ArraySize_FloatLiteral) {
// 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_EQ(r()->error(),
"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) {
// 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)),
ast::StorageClass::kPrivate);
ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"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;
// var<private> a : array<f32, size>;
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_EQ(r()->error(),
"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);
// var<private> a : array<f32, size>;
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_EQ(r()->error(),
"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) {
// var<private> a : array<f32, 0x40000000u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x40000000_u)),
ast::StorageClass::kPrivate);
ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"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) {
// var<private> a : @stride(8) array<f32, 0x20000000u>;
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0x20000000_u), 8),
ast::StorageClass::kPrivate);
ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: array size (0x100000000) must not exceed 0xffffffff bytes");
@ -330,7 +330,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_PrivateVar) {
// override size = 10i;
// var<private> a : array<f32, size>;
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_EQ(r()->error(),
"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>;
Override("size", Expr(10_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_EQ(r()->error(),
"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>;
Override("size", Expr(10_i));
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_EQ(r()->error(),
"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;
// }
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_(),
utils::Vector{
Decl(Var("a", Expr(Source{{12, 34}}, "w"))),
@ -431,7 +431,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Override_FunctionLet_Implicit) {
// let a = w;
// }
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_(),
utils::Vector{
Decl(Let("a", Expr(Source{{12, 34}}, "w"))),
@ -468,15 +468,15 @@ TEST_F(ResolverTypeValidationTest, ArraySize_Workgroup_Overridable) {
// var<workgroup> a : array<f32, size>;
Override("size", Expr(10_i));
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")),
ast::StorageClass::kWorkgroup);
ast::AddressSpace::kWorkgroup);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_ModuleVar) {
// var<private> size : i32 = 10i;
// var<private> a : array<f32, size>;
GlobalVar("size", ty.i32(), Expr(10_i), ast::StorageClass::kPrivate);
GlobalVar("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), 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::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
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_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)");
}
@ -631,7 +631,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInStructInArray) {
Structure("Foo", utils::Vector{Member("rt", ty.array<f32>())});
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_EQ(r()->error(),
@ -676,12 +676,12 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) {
}
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());
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)");
}
@ -692,7 +692,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
ASSERT_FALSE(r()->Resolve());
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)");
}
@ -717,7 +717,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
EXPECT_FALSE(r()->Resolve()) << 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)");
}
@ -725,7 +725,7 @@ TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsParameter_Fail) {
// fn func(a : ptr<workgroup, array<u32>>) {}
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_(),
utils::Vector{
@ -734,7 +734,7 @@ TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsParameter_Fail) {
EXPECT_FALSE(r()->Resolve()) << 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)");
}
@ -774,7 +774,7 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) {
TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) {
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_EQ(r()->error(),
@ -784,8 +784,8 @@ TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) {
TEST_F(ResolverTypeValidationTest, VariableAsType) {
// var<private> a : i32;
// var<private> b : a;
GlobalVar("a", ty.i32(), ast::StorageClass::kPrivate);
GlobalVar("b", ty.type_name("a"), ast::StorageClass::kPrivate);
GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate);
GlobalVar("b", ty.type_name("a"), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@ -797,7 +797,7 @@ TEST_F(ResolverTypeValidationTest, FunctionAsType) {
// fn f() {}
// var<private> v : f;
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_EQ(r()->error(),
@ -807,7 +807,7 @@ note: 'f' declared here)");
TEST_F(ResolverTypeValidationTest, BuiltinAsType) {
// 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_EQ(r()->error(), "error: cannot use builtin 'max' as type");
@ -818,14 +818,14 @@ TEST_F(ResolverTypeValidationTest, F16TypeUsedWithExtension) {
// var<private> v : f16;
Enable(ast::Extension::kF16);
GlobalVar("v", ty.f16(), ast::StorageClass::kPrivate);
GlobalVar("v", ty.f16(), ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, F16TypeUsedWithoutExtension) {
// var<private> v : f16;
GlobalVar("v", ty.f16(), ast::StorageClass::kPrivate);
GlobalVar("v", ty.f16(), ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "error: f16 used without 'f16' extension enabled");
@ -1179,7 +1179,7 @@ TEST_P(ValidMatrixTypes, Okay) {
Enable(ast::Extension::kF16);
GlobalVar("a", ty.mat(params.elem_ty(*this), params.columns, params.rows),
ast::StorageClass::kPrivate);
ast::AddressSpace::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@ -1217,7 +1217,7 @@ TEST_P(InvalidMatrixElementTypes, InvalidElementType) {
Enable(ast::Extension::kF16);
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_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);
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();
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@ -1292,7 +1292,7 @@ TEST_P(InvalidVectorElementTypes, InvalidElementType) {
Enable(ast::Extension::kF16);
GlobalVar("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width),
ast::StorageClass::kPrivate);
ast::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' "

View File

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

View File

@ -5291,7 +5291,7 @@ TEST_F(UniformityAnalysisTest, MaximumNumberOfPointerParameters) {
foo_body.Push(b.Decl(b.Let("rhs", rhs_init)));
for (int i = 0; i < 255; i++) {
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) {
foo_body.Push(b.Assign(b.Deref("p" + std::to_string(i)), "rhs"));
}
@ -5310,7 +5310,7 @@ TEST_F(UniformityAnalysisTest, MaximumNumberOfPointerParameters) {
// 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::Expression*, 8> args;
for (int i = 0; i < 255; i++) {
@ -6519,7 +6519,7 @@ TEST_F(UniformityAnalysisTest, StressGraphTraversalDepth) {
// 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;
std::string v_last = "v0";
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) {
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate);
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::AddressSpace::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Func(Source{{9, 10}}, "f0", utils::Empty, ty.vec4<f32>(),
@ -93,8 +93,8 @@ TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInFragmentStage) {
// f1();
//}
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate);
GlobalVar(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::AddressSpace::kWorkgroup);
GlobalVar("dst", ty.vec4<f32>(), ast::AddressSpace::kPrivate);
auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Func(Source{{5, 6}}, "f2", utils::Empty, ty.void_(), utils::Vector{stmt});
@ -226,7 +226,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
// 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_(),
utils::Vector{
@ -299,8 +299,8 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableDifferentScope_Fail) {
EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'a'");
}
TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) {
auto* var = Var("var", ty.i32(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverValidationTest, AddressSpace_FunctionVariableWorkgroupClass) {
auto* var = Var("var", ty.i32(), ast::AddressSpace::kWorkgroup);
Func("func", utils::Empty, ty.void_(),
utils::Vector{
@ -310,11 +310,11 @@ TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) {
EXPECT_FALSE(r()->Resolve());
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) {
auto* var = Var("s", ty.i32(), ast::StorageClass::kPrivate);
TEST_F(ResolverValidationTest, AddressSpace_FunctionVariableI32) {
auto* var = Var("s", ty.i32(), ast::AddressSpace::kPrivate);
Func("func", utils::Empty, ty.void_(),
utils::Vector{
@ -324,31 +324,31 @@ TEST_F(ResolverValidationTest, StorageClass_FunctionVariableI32) {
EXPECT_FALSE(r()->Resolve());
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);
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_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());
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_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) {
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");
@ -360,7 +360,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
}
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");
@ -373,7 +373,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
}
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* mem = MemberAccessor("my_vec", ident);
@ -384,7 +384,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) {
}
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* mem = MemberAccessor("my_vec", ident);
@ -417,7 +417,7 @@ TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) {
// let x: f32 = (*p).z;
// 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* z = Expr(Source{{{3, 3}, {3, 8}}}, "z");
auto* accessor_expr = MemberAccessor(star_p, z);
@ -435,7 +435,7 @@ TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncBadParent) {
// let x: f32 = *p.z;
// 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* accessor_expr = MemberAccessor(p, z);
auto* star_p = Deref(accessor_expr);
@ -1312,8 +1312,8 @@ TEST_F(ResolverValidationTest, OffsetAndAlignAndSizeAttribute) {
TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
auto* vf = Var("vf", ty.f32());
auto* c =
Construct(Source{{12, 34}}, ty.pointer<i32>(ast::StorageClass::kFunction), ExprList(vf));
auto* ip = Let("ip", ty.pointer<i32>(ast::StorageClass::kFunction), c);
Construct(Source{{12, 34}}, ty.pointer<i32>(ast::AddressSpace::kFunction), ExprList(vf));
auto* ip = Let("ip", ty.pointer<i32>(ast::AddressSpace::kFunction), c);
WrapInFunction(Decl(vf), Decl(ip));
EXPECT_FALSE(r()->Resolve());

View File

@ -322,7 +322,7 @@ bool Validator::Materialize(const sem::Type* to,
}
bool Validator::VariableInitializer(const ast::Variable* v,
ast::StorageClass storage_class,
ast::AddressSpace address_space,
const sem::Type* storage_ty,
const sem::Expression* initializer) const {
auto* initializer_ty = initializer->Type();
@ -338,17 +338,17 @@ bool Validator::VariableInitializer(const ast::Variable* v,
}
if (v->Is<ast::Var>()) {
switch (storage_class) {
case ast::StorageClass::kPrivate:
case ast::StorageClass::kFunction:
switch (address_space) {
case ast::AddressSpace::kPrivate:
case ast::AddressSpace::kFunction:
break; // Allowed an initializer
default:
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
// Optionally has an initializer expression, if the variable is in the
// private or function storage classes.
AddError("var of storage class '" + utils::ToString(storage_class) +
// private or function address spacees.
AddError("var of address space '" + utils::ToString(address_space) +
"' cannot have an initializer. var initializers are only "
"supported for the storage classes "
"supported for the address spacees "
"'private' and 'function'",
v->source);
return false;
@ -358,18 +358,19 @@ bool Validator::VariableInitializer(const ast::Variable* v,
return true;
}
bool Validator::StorageClassLayout(const sem::Type* store_ty,
ast::StorageClass sc,
bool Validator::AddressSpaceLayout(const sem::Type* store_ty,
ast::AddressSpace address_space,
Source source,
ValidTypeStorageLayouts& layouts) const {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class-layout-constraints
auto is_uniform_struct_or_array = [sc](const sem::Type* ty) {
return sc == ast::StorageClass::kUniform && ty->IsAnyOf<sem::Array, sem::Struct>();
auto is_uniform_struct_or_array = [address_space](const sem::Type* ty) {
return address_space == ast::AddressSpace::kUniform &&
ty->IsAnyOf<sem::Array, sem::Struct>();
};
auto is_uniform_struct = [sc](const sem::Type* ty) {
return sc == ast::StorageClass::kUniform && ty->Is<sem::Struct>();
auto is_uniform_struct = [address_space](const sem::Type* ty) {
return address_space == ast::AddressSpace::kUniform && ty->Is<sem::Struct>();
};
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);
};
// Cache result of type + storage class pair.
if (!layouts.emplace(store_ty, sc).second) {
// Cache result of type + address space pair.
if (!layouts.emplace(store_ty, address_space).second) {
return true;
}
if (!ast::IsHostShareable(sc)) {
if (!ast::IsHostShareable(address_space)) {
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
// "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))) {
AddError(
"using f16 types in '" + utils::ToString(sc) + "' storage class is not implemented yet",
source);
AddError("using f16 types in '" + utils::ToString(address_space) +
"' address space is not implemented yet",
source);
return false;
}
@ -410,7 +411,8 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
uint32_t required_align = required_alignment_of(m->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_),
str->Declaration()->source);
return false;
@ -420,7 +422,7 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
if (m->Offset() % required_align != 0) {
AddError("the offset of a struct member of type '" +
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) +
" bytes, but '" + member_name_of(m) + "' is currently at offset " +
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
// element type here, but we can't easily get that from the semantic node.
// 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;
}
if (sc == ast::StorageClass::kUniform) {
if (address_space == ast::AddressSpace::kUniform) {
// 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
// of 16 bytes.
@ -516,22 +518,22 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
return true;
}
bool Validator::StorageClassLayout(const sem::Variable* var,
bool Validator::AddressSpaceLayout(const sem::Variable* var,
const ast::Extensions& enabled_extensions,
ValidTypeStorageLayouts& layouts) const {
if (var->StorageClass() == ast::StorageClass::kPushConstant &&
if (var->AddressSpace() == ast::AddressSpace::kPushConstant &&
!enabled_extensions.Contains(ast::Extension::kChromiumExperimentalPushConstant) &&
IsValidationEnabled(var->Declaration()->attributes,
ast::DisabledValidation::kIgnoreStorageClass)) {
ast::DisabledValidation::kIgnoreAddressSpace)) {
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'",
var->Declaration()->source);
return false;
}
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);
return false;
}
@ -540,7 +542,7 @@ bool Validator::StorageClassLayout(const sem::Variable* var,
if (var->Declaration()->type) {
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;
}
}
@ -559,7 +561,7 @@ bool Validator::LocalVariable(const sem::Variable* local) const {
decl, //
[&](const ast::Var* var) {
if (IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreStorageClass)) {
ast::DisabledValidation::kIgnoreAddressSpace)) {
if (!local->Type()->UnwrapRef()->IsConstructible()) {
AddError("function-scope 'var' must have a constructible type",
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<const sem::Type*, const Source&>& atomic_composite_info) const {
auto* decl = global->Declaration();
if (global->StorageClass() != ast::StorageClass::kWorkgroup &&
if (global->AddressSpace() != ast::AddressSpace::kWorkgroup &&
IsArrayWithOverrideCount(global->Type())) {
RaiseArrayWithOverrideCountError(decl->type ? decl->type->source
: decl->constructor->source);
@ -599,8 +601,8 @@ bool Validator::GlobalVariable(
return false;
}
if (global->StorageClass() == ast::StorageClass::kNone) {
AddError("module-scope 'var' declaration must have a storage class", decl->source);
if (global->AddressSpace() == ast::AddressSpace::kNone) {
AddError("module-scope 'var' declaration must have a address space", decl->source);
return false;
}
@ -608,11 +610,11 @@ bool Validator::GlobalVariable(
bool is_shader_io_attribute =
attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute,
ast::InvariantAttribute, ast::LocationAttribute>();
bool has_io_storage_class = global->StorageClass() == ast::StorageClass::kIn ||
global->StorageClass() == ast::StorageClass::kOut;
bool has_io_address_space = global->AddressSpace() == ast::AddressSpace::kIn ||
global->AddressSpace() == ast::AddressSpace::kOut;
if (!attr->IsAnyOf<ast::BindingAttribute, ast::GroupAttribute,
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'",
attr->source);
return false;
@ -621,9 +623,9 @@ bool Validator::GlobalVariable(
// https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration
// 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 (global->StorageClass() == ast::StorageClass::kStorage) {
if (global->AddressSpace() == ast::AddressSpace::kStorage) {
// The access mode for the storage address space can only be 'read' or
// 'read_write'.
if (var->declared_access == ast::Access::kWrite) {
@ -632,7 +634,7 @@ bool Validator::GlobalVariable(
return false;
}
} 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);
return false;
}
@ -672,15 +674,15 @@ bool Validator::GlobalVariable(
return false;
}
if (global->StorageClass() == ast::StorageClass::kFunction) {
AddError("module-scope 'var' must not use storage class 'function'", decl->source);
if (global->AddressSpace() == ast::AddressSpace::kFunction) {
AddError("module-scope 'var' must not use address space 'function'", decl->source);
return false;
}
switch (global->StorageClass()) {
case ast::StorageClass::kUniform:
case ast::StorageClass::kStorage:
case ast::StorageClass::kHandle: {
switch (global->AddressSpace()) {
case ast::AddressSpace::kUniform:
case ast::AddressSpace::kStorage:
case ast::AddressSpace::kHandle: {
// https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
// Each resource variable must be declared with both group and binding
// attributes.
@ -712,29 +714,32 @@ bool Validator::GlobalVariable(
bool Validator::AtomicVariable(
const sem::Variable* var,
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 access = var->Access();
auto* type = var->Type()->UnwrapRef();
auto source = decl->type ? decl->type->source : decl->source;
if (type->Is<sem::Atomic>()) {
if (sc != ast::StorageClass::kWorkgroup && sc != ast::StorageClass::kStorage) {
AddError("atomic variables must have <storage> or <workgroup> storage class", source);
if (address_space != ast::AddressSpace::kWorkgroup &&
address_space != ast::AddressSpace::kStorage) {
AddError("atomic variables must have <storage> or <workgroup> address space", source);
return false;
}
} else if (type->IsAnyOf<sem::Struct, sem::Array>()) {
auto found = atomic_composite_info.find(type);
if (found != atomic_composite_info.end()) {
if (sc != ast::StorageClass::kStorage && sc != ast::StorageClass::kWorkgroup) {
AddError("atomic variables must have <storage> or <workgroup> storage class",
if (address_space != ast::AddressSpace::kStorage &&
address_space != ast::AddressSpace::kWorkgroup) {
AddError("atomic variables must have <storage> or <workgroup> address space",
source);
AddNote("atomic sub-type of '" + sem_.TypeNameOf(type) + "' is declared here",
found->second);
return false;
} else if (sc == ast::StorageClass::kStorage && access != ast::Access::kReadWrite) {
} else if (address_space == ast::AddressSpace::kStorage &&
access != ast::Access::kReadWrite) {
AddError(
"atomic variables in <storage> storage class must have read_write "
"atomic variables in <storage> address space must have read_write "
"access mode",
source);
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;
}
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
// If the store type is a texture type or a sampler type, then the
// variable declaration must not have a storage class attribute. The
// storage class will always be handle.
// variable declaration must not have a address space attribute. The
// address space will always be handle.
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);
return false;
}
if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreStorageClass) &&
(var->declared_storage_class == ast::StorageClass::kIn ||
var->declared_storage_class == ast::StorageClass::kOut)) {
AddError("invalid use of input/output storage class", var->source);
if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreAddressSpace) &&
(var->declared_address_space == ast::AddressSpace::kIn ||
var->declared_address_space == ast::AddressSpace::kOut)) {
AddError("invalid use of input/output address space", var->source);
return false;
}
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>()) {
auto sc = ref->StorageClass();
if (!(sc == ast::StorageClass::kFunction || sc == ast::StorageClass::kPrivate ||
sc == ast::StorageClass::kWorkgroup) &&
IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreStorageClass)) {
auto address_space = ref->AddressSpace();
if (!(address_space == ast::AddressSpace::kFunction ||
address_space == ast::AddressSpace::kPrivate ||
address_space == ast::AddressSpace::kWorkgroup) &&
IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreAddressSpace)) {
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);
return false;
}
@ -1954,7 +1961,7 @@ bool Validator::PipelineStages(const std::vector<sem::Function*>& entry_points)
auto stage = entry_point->Declaration()->PipelineStage();
if (stage != ast::PipelineStage::kCompute) {
for (auto* var : func->DirectlyReferencedGlobals()) {
if (var->StorageClass() == ast::StorageClass::kWorkgroup) {
if (var->AddressSpace() == ast::AddressSpace::kWorkgroup) {
std::stringstream stage_name;
stage_name << stage;
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) {
for (auto* var : func->DirectlyReferencedGlobals()) {
if (var->StorageClass() != ast::StorageClass::kPushConstant ||
if (var->AddressSpace() != ast::AddressSpace::kPushConstant ||
var == push_constant_var) {
continue;
}

View File

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

View File

@ -78,7 +78,7 @@ TEST_F(ValidatorIsStorableTest, Matrix) {
}
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);
EXPECT_FALSE(v()->IsStorable(ptr));
}

View File

@ -238,7 +238,7 @@ TEST_F(ResolverVariableTest, LocalVar_ShadowsGlobalVar) {
// 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"));
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* s = Let("s", ty.Of(S), s_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_(),
utils::Vector{
@ -470,7 +470,7 @@ TEST_F(ResolverVariableTest, LocalLet_InheritsAccessFromOriginatingVariable) {
// }
auto* inner = Structure("Inner", utils::Vector{Member("arr", ty.array<i32, 4>())});
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));
auto* expr = IndexAccessor(MemberAccessor(MemberAccessor(storage, "inner"), "arr"), 3_i);
@ -552,7 +552,7 @@ TEST_F(ResolverVariableTest, LocalLet_ShadowsGlobalVar) {
// 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"));
Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(l)});
@ -762,7 +762,7 @@ TEST_F(ResolverVariableTest, LocalConst_ShadowsGlobalVar) {
// 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));
Func("F", utils::Empty, ty.void_(), utils::Vector{Decl(c)});
@ -1030,16 +1030,16 @@ TEST_F(ResolverVariableTest, DISABLED_LocalConst_ConstEval) {
////////////////////////////////////////////////////////////////////////////////////////////////////
// Module-scope 'var'
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_F(ResolverVariableTest, GlobalVar_StorageClass) {
TEST_F(ResolverVariableTest, GlobalVar_AddressSpace) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
auto* buf = Structure("S", utils::Vector{Member("m", ty.i32())});
auto* private_ = GlobalVar("p", ty.i32(), ast::StorageClass::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::StorageClass::kWorkgroup);
auto* private_ = GlobalVar("p", ty.i32(), ast::AddressSpace::kPrivate);
auto* workgroup = GlobalVar("w", ty.i32(), ast::AddressSpace::kWorkgroup);
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 =
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 =
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);
}
TEST_F(ResolverVariableTest, GlobalVar_ExplicitStorageClass) {
TEST_F(ResolverVariableTest, GlobalVar_ExplicitAddressSpace) {
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class
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));
ASSERT_TRUE(r()->Resolve()) << r()->error();
@ -1220,7 +1220,7 @@ TEST_F(ResolverVariableTest, Param_ShadowsGlobalVar) {
// 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_());
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