Add support for override keyword and @id attribute

This replaces the @override keyword that was previously used for
pipeline-overridable constants.

Support for pipeline-overridable constants in Dawn is hidden behind
the "disallow-unsafe-APIs" toggle, so we can make this change directly
instead of deprecating and continuing to support the old syntax.

Fixed: tint:1403
Change-Id: I9b2957a1e33b12772bfe449c0f3a31d929f8aa8b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/80480
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2022-02-15 16:36:57 +00:00 committed by Tint LUCI CQ
parent 5f60eb72c0
commit d0ec88ce61
111 changed files with 537 additions and 534 deletions

View File

@ -11,6 +11,7 @@
### New Features ### New Features
* Module-scope declarations can now be declared in any order. [tint:1266](crbug.com/tint/1266) * Module-scope declarations can now be declared in any order. [tint:1266](crbug.com/tint/1266)
* The `override` keyword and `@id()` attribute for pipeline-overridable constants are now supported, replacing the `@override` attribute. [tint:1403](crbug.com/tint/1403)
## Changes for M99 ## Changes for M99

View File

@ -240,6 +240,8 @@ libtint_source_set("libtint_core_all_src") {
"ast/group_attribute.h", "ast/group_attribute.h",
"ast/i32.cc", "ast/i32.cc",
"ast/i32.h", "ast/i32.h",
"ast/id_attribute.cc",
"ast/id_attribute.h",
"ast/identifier_expression.cc", "ast/identifier_expression.cc",
"ast/identifier_expression.h", "ast/identifier_expression.h",
"ast/if_statement.cc", "ast/if_statement.cc",
@ -270,8 +272,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/multisampled_texture.h", "ast/multisampled_texture.h",
"ast/node.cc", "ast/node.cc",
"ast/node.h", "ast/node.h",
"ast/override_attribute.cc",
"ast/override_attribute.h",
"ast/phony_expression.cc", "ast/phony_expression.cc",
"ast/phony_expression.h", "ast/phony_expression.h",
"ast/pipeline_stage.cc", "ast/pipeline_stage.cc",

View File

@ -123,6 +123,8 @@ set(TINT_LIB_SRCS
ast/group_attribute.h ast/group_attribute.h
ast/i32.cc ast/i32.cc
ast/i32.h ast/i32.h
ast/id_attribute.cc
ast/id_attribute.h
ast/identifier_expression.cc ast/identifier_expression.cc
ast/identifier_expression.h ast/identifier_expression.h
ast/if_statement.cc ast/if_statement.cc
@ -151,8 +153,6 @@ set(TINT_LIB_SRCS
ast/multisampled_texture.h ast/multisampled_texture.h
ast/node.cc ast/node.cc
ast/node.h ast/node.h
ast/override_attribute.cc
ast/override_attribute.h
ast/phony_expression.cc ast/phony_expression.cc
ast/phony_expression.h ast/phony_expression.h
ast/pipeline_stage.cc ast/pipeline_stage.cc
@ -659,6 +659,7 @@ if(TINT_BUILD_TESTS)
ast/function_test.cc ast/function_test.cc
ast/group_attribute_test.cc ast/group_attribute_test.cc
ast/i32_test.cc ast/i32_test.cc
ast/id_attribute_test.cc
ast/identifier_expression_test.cc ast/identifier_expression_test.cc
ast/if_statement_test.cc ast/if_statement_test.cc
ast/index_accessor_expression_test.cc ast/index_accessor_expression_test.cc
@ -672,7 +673,6 @@ if(TINT_BUILD_TESTS)
ast/module_clone_test.cc ast/module_clone_test.cc
ast/module_test.cc ast/module_test.cc
ast/multisampled_texture_test.cc ast/multisampled_texture_test.cc
ast/override_attribute_test.cc
ast/phony_expression_test.cc ast/phony_expression_test.cc
ast/pointer_test.cc ast/pointer_test.cc
ast/return_statement_test.cc ast/return_statement_test.cc

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h"
#include "src/ast/test_helper.h" #include "src/ast/test_helper.h"
namespace tint { namespace tint {

42
src/ast/id_attribute.cc Normal file
View File

@ -0,0 +1,42 @@
// 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.
#include "src/ast/id_attribute.h"
#include <string>
#include "src/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::IdAttribute);
namespace tint {
namespace ast {
IdAttribute::IdAttribute(ProgramID pid, const Source& src, uint32_t val)
: Base(pid, src), value(val) {}
IdAttribute::~IdAttribute() = default;
std::string IdAttribute::Name() const {
return "id";
}
const IdAttribute* IdAttribute::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
return ctx->dst->create<IdAttribute>(src, value);
}
} // namespace ast
} // namespace tint

View File

@ -1,4 +1,4 @@
// Copyright 2020 The Tint Authors. // Copyright 2022 The Tint Authors.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef SRC_AST_OVERRIDE_ATTRIBUTE_H_ #ifndef SRC_AST_ID_ATTRIBUTE_H_
#define SRC_AST_OVERRIDE_ATTRIBUTE_H_ #define SRC_AST_ID_ATTRIBUTE_H_
#include <string> #include <string>
@ -22,19 +22,15 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
/// An override attribute /// An id attribute for pipeline-overridable constants
class OverrideAttribute : public Castable<OverrideAttribute, Attribute> { class IdAttribute : public Castable<IdAttribute, Attribute> {
public: public:
/// Create an override attribute with no specified id. /// Create an id attribute.
/// @param pid the identifier of the program that owns this node /// @param pid the identifier of the program that owns this node
/// @param src the source of this node /// @param src the source of this node
OverrideAttribute(ProgramID pid, const Source& src); /// @param val the numeric id value
/// Create an override attribute with a specific id value. IdAttribute(ProgramID pid, const Source& src, uint32_t val);
/// @param pid the identifier of the program that owns this node ~IdAttribute() override;
/// @param src the source of this node
/// @param val the override value
OverrideAttribute(ProgramID pid, const Source& src, uint32_t val);
~OverrideAttribute() override;
/// @returns the WGSL name for the attribute /// @returns the WGSL name for the attribute
std::string Name() const override; std::string Name() const override;
@ -43,16 +39,13 @@ class OverrideAttribute : public Castable<OverrideAttribute, Attribute> {
/// `ctx`. /// `ctx`.
/// @param ctx the clone context /// @param ctx the clone context
/// @return the newly cloned node /// @return the newly cloned node
const OverrideAttribute* Clone(CloneContext* ctx) const override; const IdAttribute* Clone(CloneContext* ctx) const override;
/// True if an override id was specified /// The id value
const bool has_value;
/// The override id value
const uint32_t value; const uint32_t value;
}; };
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint
#endif // SRC_AST_OVERRIDE_ATTRIBUTE_H_ #endif // SRC_AST_ID_ATTRIBUTE_H_

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/test_helper.h" #include "src/ast/test_helper.h"
@ -20,19 +20,13 @@ namespace tint {
namespace ast { namespace ast {
namespace { namespace {
using OverrideAttributeTest = TestHelper; using IdAttributeTest = TestHelper;
TEST_F(OverrideAttributeTest, Creation_WithValue) { TEST_F(IdAttributeTest, Creation) {
auto* d = create<OverrideAttribute>(12); auto* d = create<IdAttribute>(12);
EXPECT_TRUE(d->has_value);
EXPECT_EQ(12u, d->value); EXPECT_EQ(12u, d->value);
} }
TEST_F(OverrideAttributeTest, Creation_WithoutValue) {
auto* d = create<OverrideAttribute>();
EXPECT_FALSE(d->has_value);
}
} // namespace } // namespace
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h"
#include "src/ast/test_helper.h" #include "src/ast/test_helper.h"
namespace tint { namespace tint {

View File

@ -1,51 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/override_attribute.h"
#include <string>
#include "src/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::OverrideAttribute);
namespace tint {
namespace ast {
OverrideAttribute::OverrideAttribute(ProgramID pid, const Source& src)
: Base(pid, src), has_value(false), value(0) {}
OverrideAttribute::OverrideAttribute(ProgramID pid,
const Source& src,
uint32_t val)
: Base(pid, src), has_value(true), value(val) {}
OverrideAttribute::~OverrideAttribute() = default;
std::string OverrideAttribute::Name() const {
return "override";
}
const OverrideAttribute* OverrideAttribute::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
if (has_value) {
return ctx->dst->create<OverrideAttribute>(src, value);
} else {
return ctx->dst->create<OverrideAttribute>(src);
}
}
} // namespace ast
} // namespace tint

View File

@ -14,7 +14,6 @@
#include "src/ast/variable.h" #include "src/ast/variable.h"
#include "src/ast/override_attribute.h"
#include "src/program_builder.h" #include "src/program_builder.h"
#include "src/sem/variable.h" #include "src/sem/variable.h"
@ -30,17 +29,20 @@ Variable::Variable(ProgramID pid,
Access da, Access da,
const ast::Type* ty, const ast::Type* ty,
bool constant, bool constant,
bool overridable,
const Expression* ctor, const Expression* ctor,
AttributeList attrs) AttributeList attrs)
: Base(pid, src), : Base(pid, src),
symbol(sym), symbol(sym),
type(ty), type(ty),
is_const(constant), is_const(constant),
is_overridable(overridable),
constructor(ctor), constructor(ctor),
attributes(std::move(attrs)), attributes(std::move(attrs)),
declared_storage_class(dsc), declared_storage_class(dsc),
declared_access(da) { declared_access(da) {
TINT_ASSERT(AST, symbol.IsValid()); TINT_ASSERT(AST, symbol.IsValid());
TINT_ASSERT(AST, is_overridable ? is_const : true);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, constructor, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, constructor, program_id);
} }
@ -69,7 +71,8 @@ const Variable* Variable::Clone(CloneContext* ctx) const {
auto* ctor = ctx->Clone(constructor); auto* ctor = ctx->Clone(constructor);
auto attrs = ctx->Clone(attributes); auto attrs = ctx->Clone(attributes);
return ctx->dst->create<Variable>(src, sym, declared_storage_class, return ctx->dst->create<Variable>(src, sym, declared_storage_class,
declared_access, ty, is_const, ctor, attrs); declared_access, ty, is_const,
is_overridable, ctor, attrs);
} }
} // namespace ast } // namespace ast

View File

@ -46,8 +46,9 @@ struct VariableBindingPoint {
/// A Variable statement. /// A Variable statement.
/// ///
/// An instance of this class represents one of three constructs in WGSL: "var" /// An instance of this class represents one of four constructs in WGSL: "var"
/// declaration, "let" declaration, or formal parameter to a function. /// declaration, "let" declaration, "override" declaration, or formal parameter
/// to a function.
/// ///
/// 1. A "var" declaration is a name for typed storage. Examples: /// 1. A "var" declaration is a name for typed storage. Examples:
/// ///
@ -65,7 +66,14 @@ struct VariableBindingPoint {
/// ///
/// let twice_depth : i32 = width + width; // Must have initializer /// let twice_depth : i32 = width + width; // Must have initializer
/// ///
/// 3. A formal parameter to a function is a name for a typed value to /// 3. An "override" declaration is a name for a pipeline-overridable constant.
/// Examples:
///
/// override radius : i32 = 2; // Can be overridden by name.
/// @id(5) override width : i32 = 2; // Can be overridden by ID.
/// override scale : f32; // No default - must be overridden.
///
/// 4. A formal parameter to a function is a name for a typed value to
/// be passed into a function. Example: /// be passed into a function. Example:
/// ///
/// fn twice(a: i32) -> i32 { // "a:i32" is the formal parameter /// fn twice(a: i32) -> i32 { // "a:i32" is the formal parameter
@ -84,14 +92,22 @@ struct VariableBindingPoint {
/// ///
/// This class uses the term "type" to refer to: /// This class uses the term "type" to refer to:
/// the value type of a "let", /// the value type of a "let",
/// the value type of an "override",
/// the value type of the formal parameter, /// the value type of the formal parameter,
/// or the store type of the "var". /// or the store type of the "var".
// //
/// Setting is_const: /// Setting is_const:
/// - "var" gets false /// - "var" gets false
/// - "let" gets true /// - "let" gets true
/// - "override" gets true
/// - formal parameter gets true /// - formal parameter gets true
/// ///
/// Setting is_overrideable:
/// - "var" gets false
/// - "let" gets false
/// - "override" gets true
/// - formal parameter gets false
///
/// Setting storage class: /// Setting storage class:
/// - "var" is StorageClass::kNone when using the /// - "var" is StorageClass::kNone when using the
/// defaulting syntax for a "var" declared inside a function. /// defaulting syntax for a "var" declared inside a function.
@ -107,6 +123,7 @@ class Variable : public Castable<Variable, Node> {
/// @param declared_access the declared access control /// @param declared_access the declared access control
/// @param type the declared variable type /// @param type the declared variable type
/// @param is_const true if the variable is const /// @param is_const true if the variable is const
/// @param is_overridable true if the variable is pipeline-overridable
/// @param constructor the constructor expression /// @param constructor the constructor expression
/// @param attributes the variable attributes /// @param attributes the variable attributes
Variable(ProgramID program_id, Variable(ProgramID program_id,
@ -116,6 +133,7 @@ class Variable : public Castable<Variable, Node> {
Access declared_access, Access declared_access,
const ast::Type* type, const ast::Type* type,
bool is_const, bool is_const,
bool is_overridable,
const Expression* constructor, const Expression* constructor,
AttributeList attributes); AttributeList attributes);
/// Move constructor /// Move constructor
@ -143,6 +161,9 @@ class Variable : public Castable<Variable, Node> {
/// True if this is a constant, false otherwise /// True if this is a constant, false otherwise
const bool is_const; const bool is_const;
/// True if this is a pipeline-overridable constant, false otherwise
const bool is_overridable;
/// The constructor expression or nullptr if none set /// The constructor expression or nullptr if none set
const Expression* const constructor; const Expression* const constructor;

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/test_helper.h" #include "src/ast/test_helper.h"
namespace tint { namespace tint {
@ -96,13 +96,13 @@ TEST_F(VariableTest, WithAttributes) {
AttributeList{ AttributeList{
create<LocationAttribute>(1), create<LocationAttribute>(1),
create<BuiltinAttribute>(Builtin::kPosition), create<BuiltinAttribute>(Builtin::kPosition),
create<OverrideAttribute>(1200), create<IdAttribute>(1200),
}); });
auto& attributes = var->attributes; auto& attributes = var->attributes;
EXPECT_TRUE(ast::HasAttribute<ast::LocationAttribute>(attributes)); EXPECT_TRUE(ast::HasAttribute<ast::LocationAttribute>(attributes));
EXPECT_TRUE(ast::HasAttribute<ast::BuiltinAttribute>(attributes)); EXPECT_TRUE(ast::HasAttribute<ast::BuiltinAttribute>(attributes));
EXPECT_TRUE(ast::HasAttribute<ast::OverrideAttribute>(attributes)); EXPECT_TRUE(ast::HasAttribute<ast::IdAttribute>(attributes));
auto* location = ast::GetAttribute<ast::LocationAttribute>(attributes); auto* location = ast::GetAttribute<ast::LocationAttribute>(attributes);
ASSERT_NE(nullptr, location); ASSERT_NE(nullptr, location);

View File

@ -20,10 +20,10 @@
#include "src/ast/bool_literal_expression.h" #include "src/ast/bool_literal_expression.h"
#include "src/ast/call_expression.h" #include "src/ast/call_expression.h"
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/id_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/location_attribute.h" #include "src/ast/location_attribute.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/override_attribute.h"
#include "src/ast/sint_literal_expression.h" #include "src/ast/sint_literal_expression.h"
#include "src/ast/uint_literal_expression.h" #include "src/ast/uint_literal_expression.h"
#include "src/sem/array.h" #include "src/sem/array.h"
@ -213,10 +213,9 @@ std::vector<EntryPoint> Inspector::GetEntryPoints() {
overridable_constant.is_initialized = overridable_constant.is_initialized =
global->Declaration()->constructor; global->Declaration()->constructor;
auto* override_attr = ast::GetAttribute<ast::OverrideAttribute>(
global->Declaration()->attributes);
overridable_constant.is_numeric_id_specified = overridable_constant.is_numeric_id_specified =
override_attr ? override_attr->has_value : false; ast::HasAttribute<ast::IdAttribute>(
global->Declaration()->attributes);
entry_point.overridable_constants.push_back(overridable_constant); entry_point.overridable_constants.push_back(overridable_constant);
} }

View File

@ -15,7 +15,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/disable_validation_attribute.h" #include "src/ast/disable_validation_attribute.h"
#include "src/ast/override_attribute.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
#include "src/ast/workgroup_attribute.h" #include "src/ast/workgroup_attribute.h"

View File

@ -22,7 +22,7 @@
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/disable_validation_attribute.h" #include "src/ast/disable_validation_attribute.h"
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
#include "src/ast/workgroup_attribute.h" #include "src/ast/workgroup_attribute.h"
@ -109,10 +109,7 @@ class InspectorBuilder : public ProgramBuilder {
uint32_t id, uint32_t id,
const ast::Type* type, const ast::Type* type,
const ast::Expression* constructor) { const ast::Expression* constructor) {
return GlobalConst(name, type, constructor, return Override(name, type, constructor, {Id(id)});
ast::AttributeList{
Override(id),
});
} }
/// Add a pipeline constant to the global variables, without a specific ID. /// Add a pipeline constant to the global variables, without a specific ID.
@ -125,10 +122,7 @@ class InspectorBuilder : public ProgramBuilder {
std::string name, std::string name,
const ast::Type* type, const ast::Type* type,
const ast::Expression* constructor) { const ast::Expression* constructor) {
return GlobalConst(name, type, constructor, return Override(name, type, constructor);
ast::AttributeList{
Override(),
});
} }
/// Generates a function that references module-scoped, plain-typed constant /// Generates a function that references module-scoped, plain-typed constant

View File

@ -43,6 +43,7 @@
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/for_loop_statement.h" #include "src/ast/for_loop_statement.h"
#include "src/ast/i32.h" #include "src/ast/i32.h"
#include "src/ast/id_attribute.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/index_accessor_expression.h" #include "src/ast/index_accessor_expression.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
@ -52,7 +53,6 @@
#include "src/ast/member_accessor_expression.h" #include "src/ast/member_accessor_expression.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/multisampled_texture.h" #include "src/ast/multisampled_texture.h"
#include "src/ast/override_attribute.h"
#include "src/ast/phony_expression.h" #include "src/ast/phony_expression.h"
#include "src/ast/pointer.h" #include "src/ast/pointer.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
@ -1333,7 +1333,8 @@ class ProgramBuilder {
OPTIONAL&&... optional) { OPTIONAL&&... optional) {
VarOptionals opts(std::forward<OPTIONAL>(optional)...); VarOptionals opts(std::forward<OPTIONAL>(optional)...);
return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage, return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage,
opts.access, type, false, opts.constructor, opts.access, type, false /* is_const */,
false /* is_overridable */, opts.constructor,
std::move(opts.attributes)); std::move(opts.attributes));
} }
@ -1355,9 +1356,10 @@ class ProgramBuilder {
const ast::Type* type, const ast::Type* type,
OPTIONAL&&... optional) { OPTIONAL&&... optional) {
VarOptionals opts(std::forward<OPTIONAL>(optional)...); VarOptionals opts(std::forward<OPTIONAL>(optional)...);
return create<ast::Variable>(source, Sym(std::forward<NAME>(name)), return create<ast::Variable>(
opts.storage, opts.access, type, false, source, Sym(std::forward<NAME>(name)), opts.storage, opts.access, type,
opts.constructor, std::move(opts.attributes)); false /* is_const */, false /* is_overridable */, opts.constructor,
std::move(opts.attributes));
} }
/// @param name the variable name /// @param name the variable name
@ -1372,7 +1374,8 @@ class ProgramBuilder {
ast::AttributeList attributes = {}) { ast::AttributeList attributes = {}) {
return create<ast::Variable>( return create<ast::Variable>(
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, constructor, attributes); ast::Access::kUndefined, type, true /* is_const */,
false /* is_overridable */, constructor, attributes);
} }
/// @param source the variable source /// @param source the variable source
@ -1389,7 +1392,8 @@ class ProgramBuilder {
ast::AttributeList attributes = {}) { ast::AttributeList attributes = {}) {
return create<ast::Variable>( return create<ast::Variable>(
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, constructor, attributes); ast::Access::kUndefined, type, true /* is_const */,
false /* is_overridable */, constructor, attributes);
} }
/// @param name the parameter name /// @param name the parameter name
@ -1402,7 +1406,8 @@ class ProgramBuilder {
ast::AttributeList attributes = {}) { ast::AttributeList attributes = {}) {
return create<ast::Variable>( return create<ast::Variable>(
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, nullptr, attributes); ast::Access::kUndefined, type, true /* is_const */,
false /* is_overridable */, nullptr, attributes);
} }
/// @param source the parameter source /// @param source the parameter source
@ -1417,7 +1422,8 @@ class ProgramBuilder {
ast::AttributeList attributes = {}) { ast::AttributeList attributes = {}) {
return create<ast::Variable>( return create<ast::Variable>(
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true, nullptr, attributes); ast::Access::kUndefined, type, true /* is_const */,
false /* is_overridable */, nullptr, attributes);
} }
/// @param name the variable name /// @param name the variable name
@ -1506,6 +1512,47 @@ class ProgramBuilder {
return var; return var;
} }
/// @param name the variable name
/// @param type the variable type
/// @param constructor optional constructor expression
/// @param attributes optional variable attributes
/// @returns an overridable const `ast::Variable` which is automatically
/// registered as a global variable with the ast::Module.
template <typename NAME>
const ast::Variable* Override(NAME&& name,
const ast::Type* type,
const ast::Expression* constructor,
ast::AttributeList attributes = {}) {
auto* var = create<ast::Variable>(
source_, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true /* is_const */,
true /* is_overridable */, constructor, std::move(attributes));
AST().AddGlobalVariable(var);
return var;
}
/// @param source the variable source
/// @param name the variable name
/// @param type the variable type
/// @param constructor constructor expression
/// @param attributes optional variable attributes
/// @returns a const `ast::Variable` constructed by calling Var() with the
/// arguments of `args`, which is automatically registered as a global
/// variable with the ast::Module.
template <typename NAME>
const ast::Variable* Override(const Source& source,
NAME&& name,
const ast::Type* type,
const ast::Expression* constructor,
ast::AttributeList attributes = {}) {
auto* var = create<ast::Variable>(
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
ast::Access::kUndefined, type, true /* is_const */,
true /* is_overridable */, constructor, std::move(attributes));
AST().AddGlobalVariable(var);
return var;
}
/// @param source the source information /// @param source the source information
/// @param expr the expression to take the address of /// @param expr the expression to take the address of
/// @return an ast::UnaryOpExpression that takes the address of `expr` /// @return an ast::UnaryOpExpression that takes the address of `expr`
@ -2382,31 +2429,18 @@ class ProgramBuilder {
return create<ast::LocationAttribute>(source_, location); return create<ast::LocationAttribute>(source_, location);
} }
/// Creates an ast::OverrideAttribute with a specific constant ID /// Creates an ast::IdAttribute
/// @param source the source information /// @param source the source information
/// @param id the id value /// @param id the id value
/// @returns the override attribute pointer /// @returns the override attribute pointer
const ast::OverrideAttribute* Override(const Source& source, uint32_t id) { const ast::IdAttribute* Id(const Source& source, uint32_t id) {
return create<ast::OverrideAttribute>(source, id); return create<ast::IdAttribute>(source, id);
} }
/// Creates an ast::OverrideAttribute with a specific constant ID /// Creates an ast::IdAttribute with a constant ID
/// @param id the optional id value /// @param id the optional id value
/// @returns the override attribute pointer /// @returns the override attribute pointer
const ast::OverrideAttribute* Override(uint32_t id) { const ast::IdAttribute* Id(uint32_t id) { return Id(source_, id); }
return Override(source_, id);
}
/// Creates an ast::OverrideAttribute without a constant ID
/// @param source the source information
/// @returns the override attribute pointer
const ast::OverrideAttribute* Override(const Source& source) {
return create<ast::OverrideAttribute>(source);
}
/// Creates an ast::OverrideAttribute without a constant ID
/// @returns the override attribute pointer
const ast::OverrideAttribute* Override() { return Override(source_); }
/// Creates an ast::StageAttribute /// Creates an ast::StageAttribute
/// @param source the source information /// @param source the source information

View File

@ -1440,8 +1440,8 @@ bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) {
auto* type = parser_impl_.ConvertType(param->type_id()); auto* type = parser_impl_.ConvertType(param->type_id());
if (type != nullptr) { if (type != nullptr) {
auto* ast_param = parser_impl_.MakeVariable( auto* ast_param = parser_impl_.MakeVariable(
param->result_id(), ast::StorageClass::kNone, type, true, nullptr, param->result_id(), ast::StorageClass::kNone, type, true, false,
ast::AttributeList{}); nullptr, ast::AttributeList{});
// Parameters are treated as const declarations. // Parameters are treated as const declarations.
ast_params.emplace_back(ast_param); ast_params.emplace_back(ast_param);
// The value is accessible by name. // The value is accessible by name.
@ -2542,7 +2542,7 @@ bool FunctionEmitter::EmitFunctionVariables() {
} }
auto* var = parser_impl_.MakeVariable( auto* var = parser_impl_.MakeVariable(
inst.result_id(), ast::StorageClass::kNone, var_store_type, false, inst.result_id(), ast::StorageClass::kNone, var_store_type, false,
constructor, ast::AttributeList{}); false, constructor, ast::AttributeList{});
auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var); auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var);
AddStatement(var_decl_stmt); AddStatement(var_decl_stmt);
auto* var_type = ty_.Reference(var_store_type, ast::StorageClass::kNone); auto* var_type = ty_.Reference(var_store_type, ast::StorageClass::kNone);
@ -3444,9 +3444,9 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
auto* storage_type = auto* storage_type =
RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id); RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id);
AddStatement(create<ast::VariableDeclStatement>( AddStatement(create<ast::VariableDeclStatement>(
Source{}, Source{}, parser_impl_.MakeVariable(id, ast::StorageClass::kNone,
parser_impl_.MakeVariable(id, ast::StorageClass::kNone, storage_type, storage_type, false, false, nullptr,
false, nullptr, ast::AttributeList{}))); ast::AttributeList{})));
auto* type = ty_.Reference(storage_type, ast::StorageClass::kNone); auto* type = ty_.Reference(storage_type, ast::StorageClass::kNone);
identifier_types_.emplace(id, type); identifier_types_.emplace(id, type);
} }
@ -3518,8 +3518,8 @@ bool FunctionEmitter::EmitConstDefinition(
expr = AddressOfIfNeeded(expr, &inst); expr = AddressOfIfNeeded(expr, &inst);
auto* ast_const = parser_impl_.MakeVariable( auto* ast_const = parser_impl_.MakeVariable(
inst.result_id(), ast::StorageClass::kNone, expr.type, true, expr.expr, inst.result_id(), ast::StorageClass::kNone, expr.type, true, false,
ast::AttributeList{}); expr.expr, ast::AttributeList{});
if (!ast_const) { if (!ast_const) {
return false; return false;
} }

View File

@ -22,8 +22,8 @@
#include "source/opt/build_module.h" #include "source/opt/build_module.h"
#include "src/ast/bitcast_expression.h" #include "src/ast/bitcast_expression.h"
#include "src/ast/disable_validation_attribute.h" #include "src/ast/disable_validation_attribute.h"
#include "src/ast/id_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/override_attribute.h"
#include "src/ast/type_name.h" #include "src/ast/type_name.h"
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
#include "src/reader/spirv/function.h" #include "src/reader/spirv/function.h"
@ -1395,14 +1395,14 @@ bool ParserImpl::EmitScalarSpecConstants() {
"between 0 and 65535: ID %" "between 0 and 65535: ID %"
<< inst.result_id() << " has SpecId " << id; << inst.result_id() << " has SpecId " << id;
} }
auto* cid = create<ast::OverrideAttribute>(Source{}, id); auto* cid = create<ast::IdAttribute>(Source{}, id);
spec_id_decos.push_back(cid); spec_id_decos.push_back(cid);
break; break;
} }
} }
auto* ast_var = auto* ast_var =
MakeVariable(inst.result_id(), ast::StorageClass::kNone, ast_type, MakeVariable(inst.result_id(), ast::StorageClass::kNone, ast_type,
true, ast_expr, std::move(spec_id_decos)); true, true, ast_expr, std::move(spec_id_decos));
if (ast_var) { if (ast_var) {
builder_.AST().AddGlobalVariable(ast_var); builder_.AST().AddGlobalVariable(ast_var);
scalar_spec_constants_.insert(inst.result_id()); scalar_spec_constants_.insert(inst.result_id());
@ -1526,7 +1526,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
} }
auto* ast_var = auto* ast_var =
MakeVariable(var.result_id(), ast_storage_class, ast_store_type, false, MakeVariable(var.result_id(), ast_storage_class, ast_store_type, false,
ast_constructor, ast::AttributeList{}); false, ast_constructor, ast::AttributeList{});
// TODO(dneto): initializers (a.k.a. constructor expression) // TODO(dneto): initializers (a.k.a. constructor expression)
if (ast_var) { if (ast_var) {
builder_.AST().AddGlobalVariable(ast_var); builder_.AST().AddGlobalVariable(ast_var);
@ -1561,7 +1561,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
auto* ast_var = MakeVariable( auto* ast_var = MakeVariable(
builtin_position_.per_vertex_var_id, builtin_position_.per_vertex_var_id,
enum_converter_.ToStorageClass(builtin_position_.storage_class), enum_converter_.ToStorageClass(builtin_position_.storage_class),
ConvertType(builtin_position_.position_member_type_id), false, ConvertType(builtin_position_.position_member_type_id), false, false,
ast_constructor, {}); ast_constructor, {});
builder_.AST().AddGlobalVariable(ast_var); builder_.AST().AddGlobalVariable(ast_var);
@ -1598,6 +1598,7 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
ast::StorageClass sc, ast::StorageClass sc,
const Type* storage_type, const Type* storage_type,
bool is_const, bool is_const,
bool is_overridable,
const ast::Expression* constructor, const ast::Expression* constructor,
ast::AttributeList decorations) { ast::AttributeList decorations) {
if (storage_type == nullptr) { if (storage_type == nullptr) {
@ -1630,12 +1631,12 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
std::string name = namer_.Name(id); std::string name = namer_.Name(id);
// Note: we're constructing the variable here with the *storage* type, // Note: we're constructing the variable here with the *storage* type,
// regardless of whether this is a `let` or `var` declaration. // regardless of whether this is a `let`, `override`, or `var` declaration.
// `var` declarations will have a resolved type of ref<storage>, but at the // `var` declarations will have a resolved type of ref<storage>, but at the
// AST level both `var` and `let` are declared with the same type. // AST level all three are declared with the same type.
return create<ast::Variable>(Source{}, builder_.Symbols().Register(name), sc, return create<ast::Variable>(Source{}, builder_.Symbols().Register(name), sc,
access, storage_type->Build(builder_), is_const, access, storage_type->Build(builder_), is_const,
constructor, decorations); is_overridable, constructor, decorations);
} }
bool ParserImpl::ConvertDecorationsForVariable(uint32_t id, bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,

View File

@ -421,6 +421,7 @@ class ParserImpl : Reader {
/// @param sc the storage class, which cannot be ast::StorageClass::kNone /// @param sc the storage class, which cannot be ast::StorageClass::kNone
/// @param storage_type the storage type of the variable /// @param storage_type the storage type of the variable
/// @param is_const if true, the variable is const /// @param is_const if true, the variable is const
/// @param is_overridable if true, the variable is pipeline-overridable
/// @param constructor the variable constructor /// @param constructor the variable constructor
/// @param decorations the variable decorations /// @param decorations the variable decorations
/// @returns a new Variable node, or null in the ignorable variable case and /// @returns a new Variable node, or null in the ignorable variable case and
@ -429,6 +430,7 @@ class ParserImpl : Reader {
ast::StorageClass sc, ast::StorageClass sc,
const Type* storage_type, const Type* storage_type,
bool is_const, bool is_const,
bool is_overridable,
const ast::Expression* constructor, const ast::Expression* constructor,
ast::AttributeList decorations); ast::AttributeList decorations);

View File

@ -1655,7 +1655,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_True) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : bool = true;")) EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : bool = true;"))
<< module_str; << module_str;
} }
@ -1671,8 +1671,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_False) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : bool = false;"))
HasSubstr("@override(12) let myconst : bool = false;"))
<< module_str; << module_str;
} }
@ -1688,7 +1687,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_U32) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : u32 = 42u;")) EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : u32 = 42u;"))
<< module_str; << module_str;
} }
@ -1704,7 +1703,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_I32) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : i32 = 42;")) EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : i32 = 42;"))
<< module_str; << module_str;
} }
@ -1720,7 +1719,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_F32) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : f32 = 2.5;")) EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : f32 = 2.5;"))
<< module_str; << module_str;
} }
@ -1737,7 +1736,8 @@ TEST_F(SpvModuleScopeVarParserTest,
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = test::ToString(p->program()); const auto module_str = test::ToString(p->program());
EXPECT_THAT(module_str, HasSubstr("let myconst : f32 = 2.5;")) << module_str; EXPECT_THAT(module_str, HasSubstr("override myconst : f32 = 2.5;"))
<< module_str;
} }
TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_UsedInFunction) { TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_UsedInFunction) {

View File

@ -996,6 +996,8 @@ Token Lexer::check_keyword(const Source& source, std::string_view str) {
return {Token::Type::kMat4x3, source, "mat4x3"}; return {Token::Type::kMat4x3, source, "mat4x3"};
if (str == "mat4x4") if (str == "mat4x4")
return {Token::Type::kMat4x4, source, "mat4x4"}; return {Token::Type::kMat4x4, source, "mat4x4"};
if (str == "override")
return {Token::Type::kOverride, source, "override"};
if (str == "private") if (str == "private")
return {Token::Type::kPrivate, source, "private"}; return {Token::Type::kPrivate, source, "private"};
if (str == "ptr") if (str == "ptr")

View File

@ -750,6 +750,7 @@ INSTANTIATE_TEST_SUITE_P(
TokenData{"mat4x2", Token::Type::kMat4x2}, TokenData{"mat4x2", Token::Type::kMat4x2},
TokenData{"mat4x3", Token::Type::kMat4x3}, TokenData{"mat4x3", Token::Type::kMat4x3},
TokenData{"mat4x4", Token::Type::kMat4x4}, TokenData{"mat4x4", Token::Type::kMat4x4},
TokenData{"override", Token::Type::kOverride},
TokenData{"private", Token::Type::kPrivate}, TokenData{"private", Token::Type::kPrivate},
TokenData{"ptr", Token::Type::kPtr}, TokenData{"ptr", Token::Type::kPtr},
TokenData{"return", Token::Type::kReturn}, TokenData{"return", Token::Type::kReturn},

View File

@ -23,10 +23,10 @@
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/external_texture.h" #include "src/ast/external_texture.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/invariant_attribute.h" #include "src/ast/invariant_attribute.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/override_attribute.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
@ -114,10 +114,10 @@ const char kBindingAttribute[] = "binding";
const char kBlockAttribute[] = "block"; const char kBlockAttribute[] = "block";
const char kBuiltinAttribute[] = "builtin"; const char kBuiltinAttribute[] = "builtin";
const char kGroupAttribute[] = "group"; const char kGroupAttribute[] = "group";
const char kIdAttribute[] = "id";
const char kInterpolateAttribute[] = "interpolate"; const char kInterpolateAttribute[] = "interpolate";
const char kInvariantAttribute[] = "invariant"; const char kInvariantAttribute[] = "invariant";
const char kLocationAttribute[] = "location"; const char kLocationAttribute[] = "location";
const char kOverrideAttribute[] = "override";
const char kSizeAttribute[] = "size"; const char kSizeAttribute[] = "size";
const char kAlignAttribute[] = "align"; const char kAlignAttribute[] = "align";
const char kStageAttribute[] = "stage"; const char kStageAttribute[] = "stage";
@ -127,8 +127,8 @@ const char kWorkgroupSizeAttribute[] = "workgroup_size";
bool is_attribute(Token t) { bool is_attribute(Token t) {
return t == kAlignAttribute || t == kBindingAttribute || return t == kAlignAttribute || t == kBindingAttribute ||
t == kBlockAttribute || t == kBuiltinAttribute || t == kBlockAttribute || t == kBuiltinAttribute ||
t == kGroupAttribute || t == kInterpolateAttribute || t == kGroupAttribute || t == kIdAttribute ||
t == kLocationAttribute || t == kOverrideAttribute || t == kInterpolateAttribute || t == kLocationAttribute ||
t == kSizeAttribute || t == kStageAttribute || t == kStrideAttribute || t == kSizeAttribute || t == kStageAttribute || t == kStrideAttribute ||
t == kWorkgroupSizeAttribute; t == kWorkgroupSizeAttribute;
} }
@ -485,22 +485,29 @@ Maybe<const ast::Variable*> ParserImpl::global_variable_decl(
decl->access, // access control decl->access, // access control
decl->type, // type decl->type, // type
false, // is_const false, // is_const
false, // is_overridable
constructor, // constructor constructor, // constructor
std::move(attrs)); // attributes std::move(attrs)); // attributes
} }
// global_constant_decl // global_constant_decl :
// : attribute_list* LET variable_ident_decl global_const_initializer? // | LET (ident | variable_ident_decl) global_const_initializer
// | attribute* override (ident | variable_ident_decl) (equal expression)?
// global_const_initializer // global_const_initializer
// : EQUAL const_expr // : EQUAL const_expr
Maybe<const ast::Variable*> ParserImpl::global_constant_decl( Maybe<const ast::Variable*> ParserImpl::global_constant_decl(
ast::AttributeList& attrs) { ast::AttributeList& attrs) {
if (!match(Token::Type::kLet)) { bool is_overridable = false;
const char* use = nullptr;
if (match(Token::Type::kLet)) {
use = "let declaration";
} else if (match(Token::Type::kOverride)) {
use = "override declaration";
is_overridable = true;
} else {
return Failure::kNoMatch; return Failure::kNoMatch;
} }
const char* use = "let declaration";
auto decl = expect_variable_ident_decl(use, /* allow_inferred = */ true); auto decl = expect_variable_ident_decl(use, /* allow_inferred = */ true);
if (decl.errored) if (decl.errored)
return Failure::kErrored; return Failure::kErrored;
@ -521,6 +528,7 @@ Maybe<const ast::Variable*> ParserImpl::global_constant_decl(
ast::Access::kUndefined, // access control ast::Access::kUndefined, // access control
decl->type, // type decl->type, // type
true, // is_const true, // is_const
is_overridable, // is_overridable
initializer, // constructor initializer, // constructor
std::move(attrs)); // attributes std::move(attrs)); // attributes
} }
@ -1402,6 +1410,7 @@ Expect<ast::Variable*> ParserImpl::expect_param() {
ast::Access::kUndefined, // access control ast::Access::kUndefined, // access control
decl->type, // type decl->type, // type
true, // is_const true, // is_const
false, // is_overridable
nullptr, // constructor nullptr, // constructor
std::move(attrs.value)); // attributes std::move(attrs.value)); // attributes
// Formal parameters are treated like a const declaration where the // Formal parameters are treated like a const declaration where the
@ -1660,6 +1669,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
ast::Access::kUndefined, // access control ast::Access::kUndefined, // access control
decl->type, // type decl->type, // type
true, // is_const true, // is_const
false, // is_overridable
constructor.value, // constructor constructor.value, // constructor
ast::AttributeList{}); // attributes ast::AttributeList{}); // attributes
@ -1690,6 +1700,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
decl->access, // access control decl->access, // access control
decl->type, // type decl->type, // type
false, // is_const false, // is_const
false, // is_overridable
constructor, // constructor constructor, // constructor
ast::AttributeList{}); // attributes ast::AttributeList{}); // attributes
@ -3081,22 +3092,15 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
}); });
} }
if (t == kOverrideAttribute) { if (t == kIdAttribute) {
const char* use = "override attribute"; const char* use = "id attribute";
if (peek_is(Token::Type::kParenLeft)) {
// @override(x)
return expect_paren_block(use, [&]() -> Result { return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use); auto val = expect_positive_sint(use);
if (val.errored) if (val.errored)
return Failure::kErrored; return Failure::kErrored;
return create<ast::OverrideAttribute>(t.source(), val.value); return create<ast::IdAttribute>(t.source(), val.value);
}); });
} else {
// [[override]]
return create<ast::OverrideAttribute>(t.source());
}
} }
return Failure::kNoMatch; return Failure::kNoMatch;

View File

@ -54,24 +54,24 @@ fn f() { return 1 & >; }
} }
TEST_F(ParserImplErrorTest, AliasDeclInvalidAttribute) { TEST_F(ParserImplErrorTest, AliasDeclInvalidAttribute) {
EXPECT("@override type e=u32;", EXPECT("@invariant type e=u32;",
R"(test.wgsl:1:2 error: unexpected attributes R"(test.wgsl:1:2 error: unexpected attributes
@override type e=u32; @invariant type e=u32;
^^^^^^^^ ^^^^^^^^^
)"); )");
} }
// TODO(crbug.com/tint/1382): Remove // TODO(crbug.com/tint/1382): Remove
TEST_F(ParserImplErrorTest, DEPRECATED_AliasDeclInvalidAttribute) { TEST_F(ParserImplErrorTest, DEPRECATED_AliasDeclInvalidAttribute) {
EXPECT( EXPECT(
"[[override]]type e=u32;", "[[invariant]]type e=u32;",
R"(test.wgsl:1:1 warning: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style R"(test.wgsl:1:1 warning: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style
[[override]]type e=u32; [[invariant]]type e=u32;
^^ ^^
test.wgsl:1:3 error: unexpected attributes test.wgsl:1:3 error: unexpected attributes
[[override]]type e=u32; [[invariant]]type e=u32;
^^^^^^^^ ^^^^^^^^^
)"); )");
} }

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/reader/wgsl/parser_impl_test_helper.h" #include "src/reader/wgsl/parser_impl_test_helper.h"
namespace tint { namespace tint {
@ -32,6 +32,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(e->is_const); EXPECT_TRUE(e->is_const);
EXPECT_FALSE(e->is_overridable);
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(e->type, nullptr); ASSERT_NE(e->type, nullptr);
EXPECT_TRUE(e->type->Is<ast::F32>()); EXPECT_TRUE(e->type->Is<ast::F32>());
@ -43,8 +44,6 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>()); EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
EXPECT_FALSE(ast::HasAttribute<ast::OverrideAttribute>(e.value->attributes));
} }
TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) { TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
@ -59,6 +58,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(e->is_const); EXPECT_TRUE(e->is_const);
EXPECT_FALSE(e->is_overridable);
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
EXPECT_EQ(e->type, nullptr); EXPECT_EQ(e->type, nullptr);
@ -69,8 +69,6 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>()); EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
EXPECT_FALSE(ast::HasAttribute<ast::OverrideAttribute>(e.value->attributes));
} }
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) { TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
@ -100,7 +98,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
} }
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) { TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
auto p = parser("@override(7) let a : f32 = 1."); auto p = parser("@id(7) override a : f32 = 1.");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_FALSE(attrs.errored); EXPECT_FALSE(attrs.errored);
EXPECT_TRUE(attrs.matched); EXPECT_TRUE(attrs.matched);
@ -112,30 +110,30 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(e->is_const); EXPECT_TRUE(e->is_const);
EXPECT_TRUE(e->is_overridable);
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(e->type, nullptr); ASSERT_NE(e->type, nullptr);
EXPECT_TRUE(e->type->Is<ast::F32>()); EXPECT_TRUE(e->type->Is<ast::F32>());
EXPECT_EQ(e->source.range.begin.line, 1u); EXPECT_EQ(e->source.range.begin.line, 1u);
EXPECT_EQ(e->source.range.begin.column, 18u); EXPECT_EQ(e->source.range.begin.column, 17u);
EXPECT_EQ(e->source.range.end.line, 1u); EXPECT_EQ(e->source.range.end.line, 1u);
EXPECT_EQ(e->source.range.end.column, 19u); EXPECT_EQ(e->source.range.end.column, 18u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>()); EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
auto* override_attr = auto* override_attr =
ast::GetAttribute<ast::OverrideAttribute>(e.value->attributes); ast::GetAttribute<ast::IdAttribute>(e.value->attributes);
ASSERT_NE(override_attr, nullptr); ASSERT_NE(override_attr, nullptr);
EXPECT_TRUE(override_attr->has_value);
EXPECT_EQ(override_attr->value, 7u); EXPECT_EQ(override_attr->value, 7u);
} }
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) { TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
auto p = parser("[[override]] let a : f32 = 1."); auto p = parser("override a : f32 = 1.");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_FALSE(attrs.errored); EXPECT_FALSE(attrs.errored);
EXPECT_TRUE(attrs.matched); EXPECT_FALSE(attrs.matched);
auto e = p->global_constant_decl(attrs.value); auto e = p->global_constant_decl(attrs.value);
EXPECT_FALSE(p->has_error()) << p->error(); EXPECT_FALSE(p->has_error()) << p->error();
@ -144,26 +142,25 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(e->is_const); EXPECT_TRUE(e->is_const);
EXPECT_TRUE(e->is_overridable);
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(e->type, nullptr); ASSERT_NE(e->type, nullptr);
EXPECT_TRUE(e->type->Is<ast::F32>()); EXPECT_TRUE(e->type->Is<ast::F32>());
EXPECT_EQ(e->source.range.begin.line, 1u); EXPECT_EQ(e->source.range.begin.line, 1u);
EXPECT_EQ(e->source.range.begin.column, 18u); EXPECT_EQ(e->source.range.begin.column, 10u);
EXPECT_EQ(e->source.range.end.line, 1u); EXPECT_EQ(e->source.range.end.line, 1u);
EXPECT_EQ(e->source.range.end.column, 19u); EXPECT_EQ(e->source.range.end.column, 11u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>()); EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
auto* override_attr = auto* id_attr = ast::GetAttribute<ast::IdAttribute>(e.value->attributes);
ast::GetAttribute<ast::OverrideAttribute>(e.value->attributes); ASSERT_EQ(id_attr, nullptr);
ASSERT_NE(override_attr, nullptr);
EXPECT_FALSE(override_attr->has_value);
} }
TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) { TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) {
auto p = parser("@override() let a : f32 = 1."); auto p = parser("@id() override a : f32 = 1.");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_TRUE(attrs.errored); EXPECT_TRUE(attrs.errored);
EXPECT_FALSE(attrs.matched); EXPECT_FALSE(attrs.matched);
@ -175,11 +172,11 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) {
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), EXPECT_EQ(p->error(),
"1:11: expected signed integer literal for override attribute"); "1:5: expected signed integer literal for id attribute");
} }
TEST_F(ParserImplTest, GlobalConstantDec_Override_InvalidId) { TEST_F(ParserImplTest, GlobalConstantDec_Override_InvalidId) {
auto p = parser("@override(-7) let a : f32 = 1."); auto p = parser("@id(-7) override a : f32 = 1.");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_TRUE(attrs.errored); EXPECT_TRUE(attrs.errored);
EXPECT_FALSE(attrs.matched); EXPECT_FALSE(attrs.matched);
@ -190,7 +187,7 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_InvalidId) {
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:11: override attribute must be positive"); EXPECT_EQ(p->error(), "1:5: id attribute must be positive");
} }
} // namespace } // namespace

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/invariant_attribute.h"
#include "src/reader/wgsl/parser_impl_test_helper.h" #include "src/reader/wgsl/parser_impl_test_helper.h"
namespace tint { namespace tint {
@ -21,14 +21,14 @@ namespace wgsl {
namespace { namespace {
TEST_F(ParserImplTest, AttributeDecl_Parses) { TEST_F(ParserImplTest, AttributeDecl_Parses) {
auto p = parser("@override"); auto p = parser("@invariant");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_FALSE(attrs.errored); EXPECT_FALSE(attrs.errored);
EXPECT_TRUE(attrs.matched); EXPECT_TRUE(attrs.matched);
ASSERT_EQ(attrs.value.size(), 1u); ASSERT_EQ(attrs.value.size(), 1u);
auto* override_attr = attrs.value[0]->As<ast::Attribute>(); auto* invariant = attrs.value[0]->As<ast::Attribute>();
EXPECT_TRUE(override_attr->Is<ast::OverrideAttribute>()); EXPECT_TRUE(invariant->Is<ast::InvariantAttribute>());
} }
TEST_F(ParserImplTest, AttributeDecl_MissingParenLeft) { TEST_F(ParserImplTest, AttributeDecl_MissingParenLeft) {
@ -73,19 +73,19 @@ TEST_F(ParserImplTest, AttributeDecl_Invalidattribute) {
// TODO(crbug.com/tint/1382): Remove // TODO(crbug.com/tint/1382): Remove
TEST_F(ParserImplTest, DEPRECATED_attributeDecl_Parses) { TEST_F(ParserImplTest, DEPRECATED_attributeDecl_Parses) {
auto p = parser("[[override]]"); auto p = parser("[[invariant]]");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_FALSE(attrs.errored); EXPECT_FALSE(attrs.errored);
EXPECT_TRUE(attrs.matched); EXPECT_TRUE(attrs.matched);
ASSERT_EQ(attrs.value.size(), 1u); ASSERT_EQ(attrs.value.size(), 1u);
auto* override_attr = attrs.value[0]->As<ast::Attribute>(); auto* invariant_attr = attrs.value[0]->As<ast::Attribute>();
EXPECT_TRUE(override_attr->Is<ast::OverrideAttribute>()); EXPECT_TRUE(invariant_attr->Is<ast::InvariantAttribute>());
} }
// TODO(crbug.com/tint/1382): Remove // TODO(crbug.com/tint/1382): Remove
TEST_F(ParserImplTest, DEPRECATED_attributeDecl_MissingAttrRight) { TEST_F(ParserImplTest, DEPRECATED_attributeDecl_MissingAttrRight) {
auto p = parser("[[override"); auto p = parser("[[invariant");
auto attrs = p->attribute_list(); auto attrs = p->attribute_list();
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(attrs.errored); EXPECT_TRUE(attrs.errored);
@ -94,7 +94,7 @@ TEST_F(ParserImplTest, DEPRECATED_attributeDecl_MissingAttrRight) {
EXPECT_EQ( EXPECT_EQ(
p->error(), p->error(),
R"(1:1: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style R"(1:1: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style
1:11: expected ']]' for attribute list)"); 1:12: expected ']]' for attribute list)");
} }
// TODO(crbug.com/tint/1382): Remove // TODO(crbug.com/tint/1382): Remove

View File

@ -177,6 +177,8 @@ std::string_view Token::TypeToName(Type type) {
return "mat4x3"; return "mat4x3";
case Token::Type::kMat4x4: case Token::Type::kMat4x4:
return "mat4x4"; return "mat4x4";
case Token::Type::kOverride:
return "override";
case Token::Type::kPrivate: case Token::Type::kPrivate:
return "private"; return "private";
case Token::Type::kPtr: case Token::Type::kPtr:

View File

@ -187,6 +187,8 @@ class Token {
kMat4x3, kMat4x3,
/// A 'mat4x4' /// A 'mat4x4'
kMat4x4, kMat4x4,
/// A 'override'
kOverride,
/// A 'private' /// A 'private'
kPrivate, kPrivate,
/// A 'ptr' /// A 'ptr'

View File

@ -55,10 +55,10 @@ enum class AttributeKind {
kBinding, kBinding,
kBuiltin, kBuiltin,
kGroup, kGroup,
kId,
kInterpolate, kInterpolate,
kInvariant, kInvariant,
kLocation, kLocation,
kOverride,
kOffset, kOffset,
kSize, kSize,
kStage, kStage,
@ -98,6 +98,8 @@ static ast::AttributeList createAttributes(const Source& source,
return {builder.Builtin(source, ast::Builtin::kPosition)}; return {builder.Builtin(source, ast::Builtin::kPosition)};
case AttributeKind::kGroup: case AttributeKind::kGroup:
return {builder.create<ast::GroupAttribute>(source, 1u)}; return {builder.create<ast::GroupAttribute>(source, 1u)};
case AttributeKind::kId:
return {builder.create<ast::IdAttribute>(source, 0u)};
case AttributeKind::kInterpolate: case AttributeKind::kInterpolate:
return {builder.Interpolate(source, ast::InterpolationType::kLinear, return {builder.Interpolate(source, ast::InterpolationType::kLinear,
ast::InterpolationSampling::kCenter)}; ast::InterpolationSampling::kCenter)};
@ -105,8 +107,6 @@ static ast::AttributeList createAttributes(const Source& source,
return {builder.Invariant(source)}; return {builder.Invariant(source)};
case AttributeKind::kLocation: case AttributeKind::kLocation:
return {builder.Location(source, 1)}; return {builder.Location(source, 1)};
case AttributeKind::kOverride:
return {builder.create<ast::OverrideAttribute>(source, 0u)};
case AttributeKind::kOffset: case AttributeKind::kOffset:
return {builder.create<ast::StructMemberOffsetAttribute>(source, 4u)}; return {builder.create<ast::StructMemberOffsetAttribute>(source, 4u)};
case AttributeKind::kSize: case AttributeKind::kSize:
@ -152,10 +152,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -187,10 +187,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -236,10 +236,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -275,10 +275,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, true}, TestParams{AttributeKind::kBuiltin, true},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
// kInterpolate tested separately (requires [[location]]) // kInterpolate tested separately (requires [[location]])
TestParams{AttributeKind::kInvariant, true}, TestParams{AttributeKind::kInvariant, true},
TestParams{AttributeKind::kLocation, true}, TestParams{AttributeKind::kLocation, true},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -325,10 +325,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, true}, TestParams{AttributeKind::kInterpolate, true},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, true}, TestParams{AttributeKind::kLocation, true},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -373,10 +373,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -423,10 +423,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, true}, TestParams{AttributeKind::kInterpolate, true},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -469,10 +469,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, true}, TestParams{AttributeKind::kBuiltin, true},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
// kInterpolate tested separately (requires [[location]]) // kInterpolate tested separately (requires [[location]])
TestParams{AttributeKind::kInvariant, true}, TestParams{AttributeKind::kInvariant, true},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -560,10 +560,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -617,10 +617,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, true}, TestParams{AttributeKind::kBuiltin, true},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
// kInterpolate tested separately (requires [[location]]) // kInterpolate tested separately (requires [[location]])
// kInvariant tested separately (requires position builtin) // kInvariant tested separately (requires position builtin)
TestParams{AttributeKind::kLocation, true}, TestParams{AttributeKind::kLocation, true},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, true}, TestParams{AttributeKind::kOffset, true},
TestParams{AttributeKind::kSize, true}, TestParams{AttributeKind::kSize, true},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -701,10 +701,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -745,10 +745,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, false},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, false},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -810,10 +810,10 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{AttributeKind::kBinding, false}, TestParams{AttributeKind::kBinding, false},
TestParams{AttributeKind::kBuiltin, false}, TestParams{AttributeKind::kBuiltin, false},
TestParams{AttributeKind::kGroup, false}, TestParams{AttributeKind::kGroup, false},
TestParams{AttributeKind::kId, true},
TestParams{AttributeKind::kInterpolate, false}, TestParams{AttributeKind::kInterpolate, false},
TestParams{AttributeKind::kInvariant, false}, TestParams{AttributeKind::kInvariant, false},
TestParams{AttributeKind::kLocation, false}, TestParams{AttributeKind::kLocation, false},
TestParams{AttributeKind::kOverride, true},
TestParams{AttributeKind::kOffset, false}, TestParams{AttributeKind::kOffset, false},
TestParams{AttributeKind::kSize, false}, TestParams{AttributeKind::kSize, false},
TestParams{AttributeKind::kStage, false}, TestParams{AttributeKind::kStage, false},
@ -825,15 +825,15 @@ INSTANTIATE_TEST_SUITE_P(
TEST_F(ConstantAttributeTest, DuplicateAttribute) { TEST_F(ConstantAttributeTest, DuplicateAttribute) {
GlobalConst("a", ty.f32(), Expr(1.23f), GlobalConst("a", ty.f32(), Expr(1.23f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(Source{{12, 34}}), create<ast::IdAttribute>(Source{{12, 34}}, 0),
create<ast::OverrideAttribute>(Source{{56, 78}}, 1), create<ast::IdAttribute>(Source{{56, 78}}, 1),
}); });
WrapInFunction(); WrapInFunction();
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(56:78 error: duplicate override attribute R"(56:78 error: duplicate id attribute
12:34 note: first attribute declared here)"); 12:34 note: first attribute declared here)");
} }

View File

@ -404,9 +404,9 @@ class DependencyScanner {
} }
if (attr->IsAnyOf< if (attr->IsAnyOf<
ast::BindingAttribute, ast::BuiltinAttribute, ast::GroupAttribute, ast::BindingAttribute, ast::BuiltinAttribute, ast::GroupAttribute,
ast::InternalAttribute, ast::InterpolateAttribute, ast::IdAttribute, ast::InternalAttribute, ast::InterpolateAttribute,
ast::InvariantAttribute, ast::LocationAttribute, ast::InvariantAttribute, ast::LocationAttribute,
ast::OverrideAttribute, ast::StageAttribute, ast::StrideAttribute, ast::StageAttribute, ast::StrideAttribute,
ast::StructBlockAttribute, ast::StructMemberAlignAttribute, ast::StructBlockAttribute, ast::StructMemberAlignAttribute,
ast::StructMemberOffsetAttribute, ast::StructMemberOffsetAttribute,
ast::StructMemberSizeAttribute>()) { ast::StructMemberSizeAttribute>()) {

View File

@ -49,7 +49,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, NonOverridable) {
} }
TEST_F(ResolverPipelineOverridableConstantTest, WithId) { TEST_F(ResolverPipelineOverridableConstantTest, WithId) {
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override(7u)}); auto* a = Override("a", ty.f32(), Expr(1.f), {Id(7u)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -57,7 +57,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithId) {
} }
TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) { TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) {
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()}); auto* a = Override("a", ty.f32(), Expr(1.f));
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -66,12 +66,12 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) {
TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) { TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) {
std::vector<ast::Variable*> variables; std::vector<ast::Variable*> variables;
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()}); auto* a = Override("a", ty.f32(), Expr(1.f));
auto* b = GlobalConst("b", ty.f32(), Expr(1.f), {Override()}); auto* b = Override("b", ty.f32(), Expr(1.f));
auto* c = GlobalConst("c", ty.f32(), Expr(1.f), {Override(2u)}); auto* c = Override("c", ty.f32(), Expr(1.f), {Id(2u)});
auto* d = GlobalConst("d", ty.f32(), Expr(1.f), {Override(4u)}); auto* d = Override("d", ty.f32(), Expr(1.f), {Id(4u)});
auto* e = GlobalConst("e", ty.f32(), Expr(1.f), {Override()}); auto* e = Override("e", ty.f32(), Expr(1.f));
auto* f = GlobalConst("f", ty.f32(), Expr(1.f), {Override(1u)}); auto* f = Override("f", ty.f32(), Expr(1.f), {Id(1u)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -85,8 +85,8 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) {
} }
TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) { TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) {
GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 7u)}); Override("a", ty.f32(), Expr(1.f), {Id(Source{{12, 34}}, 7u)});
GlobalConst("b", ty.f32(), Expr(1.f), {Override(Source{{56, 78}}, 7u)}); Override("b", ty.f32(), Expr(1.f), {Id(Source{{56, 78}}, 7u)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -95,7 +95,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) {
} }
TEST_F(ResolverPipelineOverridableConstantTest, IdTooLarge) { TEST_F(ResolverPipelineOverridableConstantTest, IdTooLarge) {
GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 65536u)}); Override("a", ty.f32(), Expr(1.f), {Id(Source{{12, 34}}, 65536u)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -32,12 +32,12 @@
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/for_loop_statement.h" #include "src/ast/for_loop_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/matrix.h" #include "src/ast/matrix.h"
#include "src/ast/override_attribute.h"
#include "src/ast/pointer.h" #include "src/ast/pointer.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/sampled_texture.h" #include "src/ast/sampled_texture.h"
@ -333,8 +333,8 @@ sem::Variable* Resolver::Variable(const ast::Variable* var,
storage_ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS storage_ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS
} }
} else if (var->is_const && kind != VariableKind::kParameter && } else if (var->is_const && !var->is_overridable &&
!ast::HasAttribute<ast::OverrideAttribute>(var->attributes)) { kind != VariableKind::kParameter) {
AddError("let declaration must have an initializer", var->source); AddError("let declaration must have an initializer", var->source);
return nullptr; return nullptr;
} else if (!var->type) { } else if (!var->type) {
@ -426,19 +426,16 @@ sem::Variable* Resolver::Variable(const ast::Variable* var,
binding_point = {bp.group->value, bp.binding->value}; binding_point = {bp.group->value, bp.binding->value};
} }
auto* override = bool has_const_val = rhs && var->is_const && !var->is_overridable;
ast::GetAttribute<ast::OverrideAttribute>(var->attributes);
bool has_const_val = rhs && var->is_const && !override;
auto* global = builder_->create<sem::GlobalVariable>( auto* global = builder_->create<sem::GlobalVariable>(
var, var_ty, storage_class, access, var, var_ty, storage_class, access,
has_const_val ? rhs->ConstantValue() : sem::Constant{}, has_const_val ? rhs->ConstantValue() : sem::Constant{},
binding_point); binding_point);
if (override) { if (var->is_overridable) {
global->SetIsOverridable(); global->SetIsOverridable();
if (override->has_value) { if (auto* id = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
global->SetConstantId(static_cast<uint16_t>(override->value)); global->SetConstantId(static_cast<uint16_t>(id->value));
} }
} }
@ -492,18 +489,13 @@ void Resolver::AllocateOverridableConstantIds() {
// unused constant, the allocation may change on the next Resolver pass. // unused constant, the allocation may change on the next Resolver pass.
for (auto* decl : builder_->AST().GlobalDeclarations()) { for (auto* decl : builder_->AST().GlobalDeclarations()) {
auto* var = decl->As<ast::Variable>(); auto* var = decl->As<ast::Variable>();
if (!var) { if (!var || !var->is_overridable) {
continue;
}
auto* override_attr =
ast::GetAttribute<ast::OverrideAttribute>(var->attributes);
if (!override_attr) {
continue; continue;
} }
uint16_t constant_id; uint16_t constant_id;
if (override_attr->has_value) { if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
constant_id = static_cast<uint16_t>(override_attr->value); constant_id = static_cast<uint16_t>(id_attr->value);
} else { } else {
// No ID was specified, so allocate the next available ID. // No ID was specified, so allocate the next available ID.
constant_id = next_constant_id; constant_id = next_constant_id;
@ -551,11 +543,9 @@ sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* var) {
for (auto* attr : var->attributes) { for (auto* attr : var->attributes) {
Mark(attr); Mark(attr);
if (auto* override_attr = attr->As<ast::OverrideAttribute>()) { if (auto* id_attr = attr->As<ast::IdAttribute>()) {
// Track the constant IDs that are specified in the shader. // Track the constant IDs that are specified in the shader.
if (override_attr->has_value) { constant_ids_.emplace(id_attr->value, sem);
constant_ids_.emplace(override_attr->value, sem);
}
} }
} }
@ -791,8 +781,8 @@ bool Resolver::WorkgroupSize(const ast::Function* func) {
AddError(kErrBadType, expr->source); AddError(kErrBadType, expr->source);
return false; return false;
} }
// Capture the constant if an [[override]] attribute is present. // Capture the constant if it is pipeline-overridable.
if (ast::HasAttribute<ast::OverrideAttribute>(decl->attributes)) { if (decl->is_overridable) {
ws[i].overridable_const = decl; ws[i].overridable_const = decl;
} }
@ -2275,15 +2265,13 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
if (auto* ident = count_expr->As<ast::IdentifierExpression>()) { if (auto* ident = count_expr->As<ast::IdentifierExpression>()) {
// Make sure the identifier is a non-overridable module-scope constant. // Make sure the identifier is a non-overridable module-scope constant.
auto* var = ResolvedSymbol<sem::Variable>(ident); auto* var = ResolvedSymbol<sem::GlobalVariable>(ident);
if (!var || !var->Is<sem::GlobalVariable>() || if (!var || !var->Declaration()->is_const) {
!var->Declaration()->is_const) {
AddError("array size identifier must be a module-scope constant", AddError("array size identifier must be a module-scope constant",
size_source); size_source);
return nullptr; return nullptr;
} }
if (ast::HasAttribute<ast::OverrideAttribute>( if (var->IsOverridable()) {
var->Declaration()->attributes)) {
AddError("array size expression must not be pipeline-overridable", AddError("array size expression must not be pipeline-overridable",
size_source); size_source);
return nullptr; return nullptr;

View File

@ -25,9 +25,9 @@
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/id_attribute.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/override_attribute.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
@ -1011,14 +1011,14 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Consts_NestedInitializer) {
} }
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) { TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
// @override(0) let width = 16; // @id(0) override width = 16;
// @override(1) let height = 8; // @id(1) override height = 8;
// @override(2) let depth = 2; // @id(2) override depth = 2;
// @stage(compute) @workgroup_size(width, height, depth) // @stage(compute) @workgroup_size(width, height, depth)
// fn main() {} // fn main() {}
auto* width = GlobalConst("width", ty.i32(), Expr(16), {Override(0)}); auto* width = Override("width", ty.i32(), Expr(16), {Id(0)});
auto* height = GlobalConst("height", ty.i32(), Expr(8), {Override(1)}); auto* height = Override("height", ty.i32(), Expr(8), {Id(1)});
auto* depth = GlobalConst("depth", ty.i32(), Expr(2), {Override(2)}); auto* depth = Override("depth", ty.i32(), Expr(2), {Id(2)});
auto* func = Func("main", ast::VariableList{}, ty.void_(), {}, auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize("width", "height", "depth")}); WorkgroupSize("width", "height", "depth")});
@ -1037,14 +1037,14 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
} }
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) { TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
// @override(0) let width : i32; // @id(0) override width : i32;
// @override(1) let height : i32; // @id(1) override height : i32;
// @override(2) let depth : i32; // @id(2) override depth : i32;
// @stage(compute) @workgroup_size(width, height, depth) // @stage(compute) @workgroup_size(width, height, depth)
// fn main() {} // fn main() {}
auto* width = GlobalConst("width", ty.i32(), nullptr, {Override(0)}); auto* width = Override("width", ty.i32(), nullptr, {Id(0)});
auto* height = GlobalConst("height", ty.i32(), nullptr, {Override(1)}); auto* height = Override("height", ty.i32(), nullptr, {Id(1)});
auto* depth = GlobalConst("depth", ty.i32(), nullptr, {Override(2)}); auto* depth = Override("depth", ty.i32(), nullptr, {Id(2)});
auto* func = Func("main", ast::VariableList{}, ty.void_(), {}, auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize("width", "height", "depth")}); WorkgroupSize("width", "height", "depth")});
@ -1063,11 +1063,11 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
} }
TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) { TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) {
// @override(1) let height = 2; // @id(1) override height = 2;
// let depth = 3; // let depth = 3;
// @stage(compute) @workgroup_size(8, height, depth) // @stage(compute) @workgroup_size(8, height, depth)
// fn main() {} // fn main() {}
auto* height = GlobalConst("height", ty.i32(), Expr(2), {Override(0)}); auto* height = Override("height", ty.i32(), Expr(2), {Id(0)});
GlobalConst("depth", ty.i32(), Expr(3)); GlobalConst("depth", ty.i32(), Expr(3));
auto* func = Func("main", ast::VariableList{}, ty.void_(), {}, auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),

View File

@ -30,12 +30,12 @@
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/for_loop_statement.h" #include "src/ast/for_loop_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/matrix.h" #include "src/ast/matrix.h"
#include "src/ast/override_attribute.h"
#include "src/ast/pointer.h" #include "src/ast/pointer.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/sampled_texture.h" #include "src/ast/sampled_texture.h"
@ -411,16 +411,15 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
for (auto* attr : decl->attributes) { for (auto* attr : decl->attributes) {
if (decl->is_const) { if (decl->is_const) {
if (auto* override_attr = attr->As<ast::OverrideAttribute>()) { if (auto* id_attr = attr->As<ast::IdAttribute>()) {
if (override_attr->has_value) { uint32_t id = id_attr->value;
uint32_t id = override_attr->value;
auto it = constant_ids_.find(id); auto it = constant_ids_.find(id);
if (it != constant_ids_.end() && it->second != var) { if (it != constant_ids_.end() && it->second != var) {
AddError("pipeline constant IDs must be unique", attr->source); AddError("pipeline constant IDs must be unique", attr->source);
AddNote("a pipeline constant with an ID of " + std::to_string(id) + AddNote("a pipeline constant with an ID of " + std::to_string(id) +
" was previously declared " " was previously declared "
"here:", "here:",
ast::GetAttribute<ast::OverrideAttribute>( ast::GetAttribute<ast::IdAttribute>(
it->second->Declaration()->attributes) it->second->Declaration()->attributes)
->source); ->source);
return false; return false;
@ -430,7 +429,6 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
attr->source); attr->source);
return false; return false;
} }
}
} else { } else {
AddError("attribute is not valid for constants", attr->source); AddError("attribute is not valid for constants", attr->source);
return false; return false;

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
@ -79,9 +79,8 @@ TEST_F(ResolverTypeValidationTest, VariableDeclNoConstructor_Pass) {
} }
TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) { TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) {
// @override(0) let a :i32; // @id(0) override a :i32;
GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr, Override(Source{{12, 34}}, "a", ty.i32(), nullptr, ast::AttributeList{Id(0)});
ast::AttributeList{create<ast::OverrideAttribute>(0)});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -98,7 +97,7 @@ TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) {
AST().AddGlobalVariable(create<ast::Variable>( AST().AddGlobalVariable(create<ast::Variable>(
Source{{12, 34}}, Symbols().Register("global_var"), Source{{12, 34}}, Symbols().Register("global_var"),
ast::StorageClass::kPrivate, ast::Access::kUndefined, ty.f32(), true, ast::StorageClass::kPrivate, ast::Access::kUndefined, ty.f32(), true,
Expr(1.23f), ast::AttributeList{})); false, Expr(1.23f), ast::AttributeList{}));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -346,9 +345,9 @@ TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) {
} }
TEST_F(ResolverTypeValidationTest, ArraySize_OverridableConstant) { TEST_F(ResolverTypeValidationTest, ArraySize_OverridableConstant) {
// [[override]] let size = 10; // override size = 10;
// var<private> a : array<f32, size>; // var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(10), {Override()}); Override("size", nullptr, Expr(10));
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")), Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -142,7 +142,7 @@ void BindingRemapper::Run(CloneContext& ctx,
const ast::Type* inner_ty = CreateASTTypeFor(ctx, ty); const ast::Type* inner_ty = CreateASTTypeFor(ctx, ty);
auto* new_var = ctx.dst->create<ast::Variable>( auto* new_var = ctx.dst->create<ast::Variable>(
ctx.Clone(var->source), ctx.Clone(var->symbol), ctx.Clone(var->source), ctx.Clone(var->symbol),
var->declared_storage_class, ac, inner_ty, var->is_const, var->declared_storage_class, ac, inner_ty, false, false,
ctx.Clone(var->constructor), ctx.Clone(var->attributes)); ctx.Clone(var->constructor), ctx.Clone(var->attributes));
ctx.Replace(var, new_var); ctx.Replace(var, new_var);
} }

View File

@ -108,7 +108,7 @@ void CalculateArrayLength::Run(CloneContext& ctx,
// in order for HLSL to emit this as a ByteAddressBuffer. // in order for HLSL to emit this as a ByteAddressBuffer.
ctx.dst->create<ast::Variable>( ctx.dst->create<ast::Variable>(
ctx.dst->Sym("buffer"), ast::StorageClass::kStorage, ctx.dst->Sym("buffer"), ast::StorageClass::kStorage,
ast::Access::kUndefined, type, true, nullptr, ast::Access::kUndefined, type, true, false, nullptr,
ast::AttributeList{disable_validation}), ast::AttributeList{disable_validation}),
ctx.dst->Param("result", ctx.dst->Param("result",
ctx.dst->ty.pointer(ctx.dst->ty.u32(), ctx.dst->ty.pointer(ctx.dst->ty.u32(),

View File

@ -457,7 +457,7 @@ struct DecomposeMemoryAccess::State {
// array. // array.
b.create<ast::Variable>(b.Sym("buffer"), storage_class, b.create<ast::Variable>(b.Sym("buffer"), storage_class,
var_user->Variable()->Access(), var_user->Variable()->Access(),
buf_ast_ty, true, nullptr, buf_ast_ty, true, false, nullptr,
ast::AttributeList{disable_validation}), ast::AttributeList{disable_validation}),
b.Param("offset", b.ty.u32()), b.Param("offset", b.ty.u32()),
}; };
@ -556,7 +556,7 @@ struct DecomposeMemoryAccess::State {
b.create<ast::Variable>(b.Sym("buffer"), storage_class, b.create<ast::Variable>(b.Sym("buffer"), storage_class,
var_user->Variable()->Access(), var_user->Variable()->Access(),
buf_ast_ty, true, nullptr, buf_ast_ty, true, false, nullptr,
ast::AttributeList{disable_validation}), ast::AttributeList{disable_validation}),
b.Param("offset", b.ty.u32()), b.Param("offset", b.ty.u32()),
b.Param("value", el_ast_ty), b.Param("value", el_ast_ty),
@ -656,7 +656,7 @@ struct DecomposeMemoryAccess::State {
// order for HLSL to emit this as a ByteAddressBuffer. // order for HLSL to emit this as a ByteAddressBuffer.
b.create<ast::Variable>(b.Sym("buffer"), ast::StorageClass::kStorage, b.create<ast::Variable>(b.Sym("buffer"), ast::StorageClass::kStorage,
var_user->Variable()->Access(), buf_ast_ty, var_user->Variable()->Access(), buf_ast_ty,
true, nullptr, true, false, nullptr,
ast::AttributeList{disable_validation}), ast::AttributeList{disable_validation}),
b.Param("offset", b.ty.u32()), b.Param("offset", b.ty.u32()),
}; };

View File

@ -116,7 +116,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
auto clonedAttributes = ctx.Clone(var->attributes); auto clonedAttributes = ctx.Clone(var->attributes);
auto* newVar = ctx.dst->create<ast::Variable>( auto* newVar = ctx.dst->create<ast::Variable>(
clonedSrc, clonedSym, var->declared_storage_class, clonedSrc, clonedSym, var->declared_storage_class,
var->declared_access, newType, var->is_const, clonedConstructor, var->declared_access, newType, false, false, clonedConstructor,
clonedAttributes); clonedAttributes);
ctx.Replace(var, newVar); ctx.Replace(var, newVar);

View File

@ -1201,7 +1201,7 @@ INSTANTIATE_TEST_SUITE_P(
"operator", "operator",
"or", "or",
"or_eq", "or_eq",
"override", // "override", // Also used in WGSL
// "private", // Also used in WGSL // "private", // Also used in WGSL
"protected", "protected",
"public", "public",

View File

@ -1056,7 +1056,7 @@ var<private> a : mat3x2<f32>;
// TODO(dsinclair): Implement when constant_id exists // TODO(dsinclair): Implement when constant_id exists
TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) { TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) {
// @override(1300) let idx : i32; // @id(1300) override idx : i32;
// var a : vec3<f32> // var a : vec3<f32>
// var b : f32 = a[idx] // var b : f32 = a[idx]
// //
@ -1065,7 +1065,7 @@ TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) {
// TODO(dsinclair): Implement when constant_id exists // TODO(dsinclair): Implement when constant_id exists
TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) { TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) {
// @override(1300) let idx : i32; // @id(1300) override idx : i32;
// var a : array<f32, 4> // var a : array<f32, 4>
// var b : f32 = a[idx] // var b : f32 = a[idx]
// //
@ -1074,7 +1074,7 @@ TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) {
// TODO(dsinclair): Implement when constant_id exists // TODO(dsinclair): Implement when constant_id exists
TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) { TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) {
// @override(1300) let idx : i32; // @id(1300) override idx : i32;
// var a : mat3x2<f32> // var a : mat3x2<f32>
// var b : f32 = a[idx][1] // var b : f32 = a[idx][1]
// //
@ -1083,7 +1083,7 @@ TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) {
// TODO(dsinclair): Implement when constant_id exists // TODO(dsinclair): Implement when constant_id exists
TEST_F(RobustnessTest, DISABLED_Matrix_Row_Constant_Id_Clamps) { TEST_F(RobustnessTest, DISABLED_Matrix_Row_Constant_Id_Clamps) {
// @override(1300) let idx : i32; // @id(1300) override idx : i32;
// var a : mat3x2<f32> // var a : mat3x2<f32>
// var b : f32 = a[1][idx] // var b : f32 = a[1][idx]
// //

View File

@ -77,19 +77,15 @@ void SingleEntryPoint::Run(CloneContext& ctx,
ctx.dst->AST().AddTypeDecl(ctx.Clone(ty)); ctx.dst->AST().AddTypeDecl(ctx.Clone(ty));
} else if (auto* var = decl->As<ast::Variable>()) { } else if (auto* var = decl->As<ast::Variable>()) {
if (referenced_vars.count(var)) { if (referenced_vars.count(var)) {
if (var->is_const) { if (var->is_overridable) {
if (auto* attr =
ast::GetAttribute<ast::OverrideAttribute>(var->attributes)) {
// It is an overridable constant // It is an overridable constant
if (!attr->has_value) { if (!ast::HasAttribute<ast::IdAttribute>(var->attributes)) {
// If the attribute doesn't have numeric ID specified explicitly // If the constant doesn't already have an @id() attribute, add one
// Make their ids explicitly assigned in the attribute so that // so that its allocated ID so that it won't be affected by other
// they won't be affected by other stripped away constants // stripped away constants
auto* global = sem.Get(var)->As<sem::GlobalVariable>(); auto* global = sem.Get(var)->As<sem::GlobalVariable>();
const auto* new_deco = const auto* id = ctx.dst->Id(global->ConstantId());
ctx.dst->Override(attr->source, global->ConstantId()); ctx.InsertFront(var->attributes, id);
ctx.Replace(attr, new_deco);
}
} }
} }
ctx.dst->AST().AddGlobalVariable(ctx.Clone(var)); ctx.dst->AST().AddGlobalVariable(ctx.Clone(var));

View File

@ -258,10 +258,10 @@ fn main() {
TEST_F(SingleEntryPointTest, OverridableConstants) { TEST_F(SingleEntryPointTest, OverridableConstants) {
auto* src = R"( auto* src = R"(
@override(1001) let c1 : u32 = 1u; @id(1001) override c1 : u32 = 1u;
[[override]] let c2 : u32 = 1u; override c2 : u32 = 1u;
@override(0) let c3 : u32 = 1u; @id(0) override c3 : u32 = 1u;
@override(9999) let c4 : u32 = 1u; @id(9999) override c4 : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn comp_main1() { fn comp_main1() {
@ -292,7 +292,7 @@ fn comp_main5() {
{ {
SingleEntryPoint::Config cfg("comp_main1"); SingleEntryPoint::Config cfg("comp_main1");
auto* expect = R"( auto* expect = R"(
@override(1001) let c1 : u32 = 1u; @id(1001) override c1 : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn comp_main1() { fn comp_main1() {
@ -310,7 +310,7 @@ fn comp_main1() {
// The decorator is replaced with the one with explicit id // The decorator is replaced with the one with explicit id
// And should not be affected by other constants stripped away // And should not be affected by other constants stripped away
auto* expect = R"( auto* expect = R"(
@override(1) let c2 : u32 = 1u; @id(1) override c2 : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn comp_main2() { fn comp_main2() {
@ -326,7 +326,7 @@ fn comp_main2() {
{ {
SingleEntryPoint::Config cfg("comp_main3"); SingleEntryPoint::Config cfg("comp_main3");
auto* expect = R"( auto* expect = R"(
@override(0) let c3 : u32 = 1u; @id(0) override c3 : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn comp_main3() { fn comp_main3() {
@ -342,7 +342,7 @@ fn comp_main3() {
{ {
SingleEntryPoint::Config cfg("comp_main4"); SingleEntryPoint::Config cfg("comp_main4");
auto* expect = R"( auto* expect = R"(
@override(9999) let c4 : u32 = 1u; @id(9999) override c4 : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn comp_main4() { fn comp_main4() {

View File

@ -57,7 +57,7 @@ struct Unshadow::State {
auto attributes = ctx.Clone(decl->attributes); auto attributes = ctx.Clone(decl->attributes);
return ctx.dst->create<ast::Variable>( return ctx.dst->create<ast::Variable>(
source, symbol, decl->declared_storage_class, decl->declared_access, source, symbol, decl->declared_storage_class, decl->declared_access,
type, decl->is_const, constructor, attributes); type, decl->is_const, decl->is_overridable, constructor, attributes);
}; };
ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* { ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {

View File

@ -506,7 +506,7 @@ var<workgroup> b : S;
var<workgroup> c : array<S, 32>; var<workgroup> c : array<S, 32>;
@override(1) let X : i32; @id(1) override X : i32;
@stage(compute) @workgroup_size(2, 3, X) @stage(compute) @workgroup_size(2, 3, X)
fn f(@builtin(local_invocation_index) local_idx : u32) { fn f(@builtin(local_invocation_index) local_idx : u32) {
@ -528,7 +528,7 @@ var<workgroup> b : S;
var<workgroup> c : array<S, 32>; var<workgroup> c : array<S, 32>;
@override(1) let X : i32; @id(1) override X : i32;
@stage(compute) @workgroup_size(2, 3, X) @stage(compute) @workgroup_size(2, 3, X)
fn f(@builtin(local_invocation_index) local_idx : u32) { fn f(@builtin(local_invocation_index) local_idx : u32) {
@ -576,7 +576,7 @@ var<workgroup> b : S;
var<workgroup> c : array<S, 32>; var<workgroup> c : array<S, 32>;
@override(1) let X : u32; @id(1) override X : u32;
@stage(compute) @workgroup_size(5u, X, 10u) @stage(compute) @workgroup_size(5u, X, 10u)
fn f(@builtin(local_invocation_index) local_idx : u32) { fn f(@builtin(local_invocation_index) local_idx : u32) {
@ -599,7 +599,7 @@ var<workgroup> b : S;
var<workgroup> c : array<S, 32>; var<workgroup> c : array<S, 32>;
@override(1) let X : u32; @id(1) override X : u32;
@stage(compute) @workgroup_size(5u, X, 10u) @stage(compute) @workgroup_size(5u, X, 10u)
fn f(@builtin(local_invocation_index) local_idx : u32) { fn f(@builtin(local_invocation_index) local_idx : u32) {

View File

@ -23,9 +23,9 @@
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/override_attribute.h"
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/debug.h" #include "src/debug.h"
#include "src/sem/array.h" #include "src/sem/array.h"
@ -2607,7 +2607,7 @@ bool GeneratorImpl::EmitVariable(const ast::Variable* var) {
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
for (auto* d : var->attributes) { for (auto* d : var->attributes) {
if (!d->Is<ast::OverrideAttribute>()) { if (!d->Is<ast::IdAttribute>()) {
diagnostics_.add_error(diag::System::Writer, diagnostics_.add_error(diag::System::Writer,
"Decorated const values not valid"); "Decorated const values not valid");
return false; return false;

View File

@ -840,9 +840,9 @@ void main() {
TEST_F(GlslGeneratorImplTest_Function, TEST_F(GlslGeneratorImplTest_Function,
Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) { Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) {
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)}); Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)}); Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)}); Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
Func("main", ast::VariableList{}, ty.void_(), {}, Func("main", ast::VariableList{}, ty.void_(), {},
{ {
Stage(ast::PipelineStage::kCompute), Stage(ast::PipelineStage::kCompute),

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/writer/glsl/test_helper.h" #include "src/writer/glsl/test_helper.h"
namespace tint { namespace tint {
@ -33,9 +33,9 @@ TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
} }
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f), auto* var = Override("pos", ty.f32(), Expr(3.0f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(23), Id(23),
}); });
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -49,9 +49,9 @@ const float pos = WGSL_SPEC_CONSTANT_23;
} }
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) { TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) {
auto* var = GlobalConst("pos", ty.f32(), nullptr, auto* var = Override("pos", ty.f32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(23), Id(23),
}); });
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -65,14 +65,11 @@ const float pos = WGSL_SPEC_CONSTANT_23;
} }
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) { TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) {
auto* a = GlobalConst("a", ty.f32(), Expr(3.0f), auto* a = Override("a", ty.f32(), Expr(3.0f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
});
auto* b = GlobalConst("b", ty.f32(), Expr(2.0f),
ast::AttributeList{
create<ast::OverrideAttribute>(),
}); });
auto* b = Override("b", ty.f32(), Expr(2.0f));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/writer/glsl/test_helper.h" #include "src/writer/glsl/test_helper.h"

View File

@ -24,9 +24,9 @@
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/override_attribute.h"
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
#include "src/debug.h" #include "src/debug.h"
#include "src/sem/array.h" #include "src/sem/array.h"
@ -3898,7 +3898,7 @@ bool GeneratorImpl::EmitVariable(const ast::Variable* var) {
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
for (auto* d : var->attributes) { for (auto* d : var->attributes) {
if (!d->Is<ast::OverrideAttribute>()) { if (!d->Is<ast::IdAttribute>()) {
diagnostics_.add_error(diag::System::Writer, diagnostics_.add_error(diag::System::Writer,
"Decorated const values not valid"); "Decorated const values not valid");
return false; return false;

View File

@ -745,9 +745,9 @@ void main() {
TEST_F(HlslGeneratorImplTest_Function, TEST_F(HlslGeneratorImplTest_Function,
Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) { Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) {
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)}); Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)}); Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)}); Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
Func("main", ast::VariableList{}, ty.void_(), {}, Func("main", ast::VariableList{}, ty.void_(), {},
{ {
Stage(ast::PipelineStage::kCompute), Stage(ast::PipelineStage::kCompute),

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/writer/hlsl/test_helper.h" #include "src/writer/hlsl/test_helper.h"
namespace tint { namespace tint {
@ -33,9 +33,9 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
} }
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f), auto* var = Override("pos", ty.f32(), Expr(3.0f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(23), Id(23),
}); });
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -49,9 +49,9 @@ static const float pos = WGSL_SPEC_CONSTANT_23;
} }
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) { TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) {
auto* var = GlobalConst("pos", ty.f32(), nullptr, auto* var = Override("pos", ty.f32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(23), Id(23),
}); });
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -65,14 +65,11 @@ static const float pos = WGSL_SPEC_CONSTANT_23;
} }
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) { TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) {
auto* a = GlobalConst("a", ty.f32(), Expr(3.0f), auto* a = Override("a", ty.f32(), Expr(3.0f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
});
auto* b = GlobalConst("b", ty.f32(), Expr(2.0f),
ast::AttributeList{
create<ast::OverrideAttribute>(),
}); });
auto* b = Override("b", ty.f32(), Expr(2.0f));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/writer/hlsl/test_helper.h" #include "src/writer/hlsl/test_helper.h"

View File

@ -27,9 +27,9 @@
#include "src/ast/disable_validation_attribute.h" #include "src/ast/disable_validation_attribute.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/id_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/override_attribute.h"
#include "src/ast/sint_literal_expression.h" #include "src/ast/sint_literal_expression.h"
#include "src/ast/uint_literal_expression.h" #include "src/ast/uint_literal_expression.h"
#include "src/ast/variable_decl_statement.h" #include "src/ast/variable_decl_statement.h"
@ -2823,7 +2823,7 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var) {
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
for (auto* d : var->attributes) { for (auto* d : var->attributes) {
if (!d->Is<ast::OverrideAttribute>()) { if (!d->Is<ast::IdAttribute>()) {
diagnostics_.add_error(diag::System::Writer, diagnostics_.add_error(diag::System::Writer,
"Decorated const values not valid"); "Decorated const values not valid");
return false; return false;

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/writer/msl/test_helper.h" #include "src/writer/msl/test_helper.h"
namespace tint { namespace tint {
@ -33,9 +33,9 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
} }
TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
auto* var = GlobalConst("pos", ty.f32(), Expr(3.f), auto* var = Override("pos", ty.f32(), Expr(3.f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(23), Id(23),
}); });
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -45,14 +45,11 @@ TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
} }
TEST_F(MslGeneratorImplTest, Emit_SpecConstant_NoId) { TEST_F(MslGeneratorImplTest, Emit_SpecConstant_NoId) {
auto* var_a = GlobalConst("a", ty.f32(), nullptr, auto* var_a = Override("a", ty.f32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
});
auto* var_b = GlobalConst("b", ty.f32(), nullptr,
ast::AttributeList{
create<ast::OverrideAttribute>(),
}); });
auto* var_b = Override("b", ty.f32(), nullptr);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -20,8 +20,8 @@
#include "spirv/unified1/GLSL.std.450.h" #include "spirv/unified1/GLSL.std.450.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
#include "src/ast/id_attribute.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/override_attribute.h"
#include "src/ast/traverse_expressions.h" #include "src/ast/traverse_expressions.h"
#include "src/sem/array.h" #include "src/sem/array.h"
#include "src/sem/atomic_type.h" #include "src/sem/atomic_type.h"
@ -770,9 +770,8 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
if (var->is_const) { if (var->is_const) {
if (!var->constructor) { if (!var->constructor) {
// Constants must have an initializer unless they have an override // Constants must have an initializer unless they are overridable.
// attribute. if (!var->is_overridable) {
if (!ast::HasAttribute<ast::OverrideAttribute>(var->attributes)) {
error_ = "missing constructor for constant"; error_ = "missing constructor for constant";
return false; return false;
} }
@ -905,7 +904,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
Operand::Int(group->value)}); Operand::Int(group->value)});
return true; return true;
}, },
[&](const ast::OverrideAttribute*) { [&](const ast::IdAttribute*) {
return true; // Spec constants are handled elsewhere return true; // Spec constants are handled elsewhere
}, },
[&](const ast::InternalAttribute*) { [&](const ast::InternalAttribute*) {

View File

@ -155,9 +155,9 @@ TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_Const) {
} }
TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_OverridableConst) { TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_OverridableConst) {
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)}); Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)}); Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)}); Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
auto* func = Func("main", {}, ty.void_(), ast::StatementList{}, auto* func = Func("main", {}, ty.void_(), ast::StatementList{},
ast::AttributeList{ ast::AttributeList{
WorkgroupSize("width", "height", "depth"), WorkgroupSize("width", "height", "depth"),
@ -185,7 +185,7 @@ OpDecorate %3 BuiltIn WorkgroupSize
} }
TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_LiteralAndConst) { TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_LiteralAndConst) {
GlobalConst("height", ty.i32(), Construct(ty.i32(), 2), {Override(7u)}); Override("height", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 3)); GlobalConst("depth", ty.i32(), Construct(ty.i32(), 3));
auto* func = Func("main", {}, ty.void_(), ast::StatementList{}, auto* func = Func("main", {}, ty.void_(), ast::StatementList{},
ast::AttributeList{ ast::AttributeList{

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h" #include "src/ast/id_attribute.h"
#include "src/ast/stage_attribute.h" #include "src/ast/stage_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
#include "src/writer/spirv/spv_dump.h" #include "src/writer/spirv/spv_dump.h"
@ -150,9 +150,9 @@ OpDecorate %1 DescriptorSet 3
} }
TEST_F(BuilderTest, GlobalVar_Override_Bool) { TEST_F(BuilderTest, GlobalVar_Override_Bool) {
auto* v = GlobalConst("var", ty.bool_(), Expr(true), auto* v = Override("var", ty.bool_(), Expr(true),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(1200), Id(1200),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -168,9 +168,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Bool_ZeroValue) { TEST_F(BuilderTest, GlobalVar_Override_Bool_ZeroValue) {
auto* v = GlobalConst("var", ty.bool_(), Construct<bool>(), auto* v = Override("var", ty.bool_(), Construct<bool>(),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(1200), Id(1200),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -186,9 +186,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool_ZeroValue) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Bool_NoConstructor) { TEST_F(BuilderTest, GlobalVar_Override_Bool_NoConstructor) {
auto* v = GlobalConst("var", ty.bool_(), nullptr, auto* v = Override("var", ty.bool_(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(1200), Id(1200),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -204,9 +204,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool_NoConstructor) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Scalar) { TEST_F(BuilderTest, GlobalVar_Override_Scalar) {
auto* v = GlobalConst("var", ty.f32(), Expr(2.f), auto* v = Override("var", ty.f32(), Expr(2.f),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -222,9 +222,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Scalar_ZeroValue) { TEST_F(BuilderTest, GlobalVar_Override_Scalar_ZeroValue) {
auto* v = GlobalConst("var", ty.f32(), Construct<f32>(), auto* v = Override("var", ty.f32(), Construct<f32>(),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -240,9 +240,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_ZeroValue) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Scalar_F32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_Override_Scalar_F32_NoConstructor) {
auto* v = GlobalConst("var", ty.f32(), nullptr, auto* v = Override("var", ty.f32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -258,9 +258,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_F32_NoConstructor) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Scalar_I32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_Override_Scalar_I32_NoConstructor) {
auto* v = GlobalConst("var", ty.i32(), nullptr, auto* v = Override("var", ty.i32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -276,9 +276,9 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_I32_NoConstructor) {
} }
TEST_F(BuilderTest, GlobalVar_Override_Scalar_U32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_Override_Scalar_U32_NoConstructor) {
auto* v = GlobalConst("var", ty.u32(), nullptr, auto* v = Override("var", ty.u32(), nullptr,
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
}); });
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -294,14 +294,11 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_U32_NoConstructor) {
} }
TEST_F(BuilderTest, GlobalVar_Override_NoId) { TEST_F(BuilderTest, GlobalVar_Override_NoId) {
auto* var_a = GlobalConst("a", ty.bool_(), Expr(true), auto* var_a = Override("a", ty.bool_(), Expr(true),
ast::AttributeList{ ast::AttributeList{
create<ast::OverrideAttribute>(0), Id(0),
});
auto* var_b = GlobalConst("b", ty.bool_(), Expr(false),
ast::AttributeList{
create<ast::OverrideAttribute>(),
}); });
auto* var_b = Override("b", ty.bool_(), Expr(false));
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -28,13 +28,13 @@
#include "src/ast/f32.h" #include "src/ast/f32.h"
#include "src/ast/float_literal_expression.h" #include "src/ast/float_literal_expression.h"
#include "src/ast/i32.h" #include "src/ast/i32.h"
#include "src/ast/id_attribute.h"
#include "src/ast/internal_attribute.h" #include "src/ast/internal_attribute.h"
#include "src/ast/interpolate_attribute.h" #include "src/ast/interpolate_attribute.h"
#include "src/ast/invariant_attribute.h" #include "src/ast/invariant_attribute.h"
#include "src/ast/matrix.h" #include "src/ast/matrix.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/multisampled_texture.h" #include "src/ast/multisampled_texture.h"
#include "src/ast/override_attribute.h"
#include "src/ast/pointer.h" #include "src/ast/pointer.h"
#include "src/ast/sampled_texture.h" #include "src/ast/sampled_texture.h"
#include "src/ast/sint_literal_expression.h" #include "src/ast/sint_literal_expression.h"
@ -646,7 +646,9 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, const ast::Variable* var) {
out << " "; out << " ";
} }
if (var->is_const) { if (var->is_overridable) {
out << "override";
} else if (var->is_const) {
out << "let"; out << "let";
} else { } else {
out << "var"; out << "var";
@ -747,11 +749,8 @@ bool GeneratorImpl::EmitAttributes(std::ostream& out,
out << "invariant"; out << "invariant";
return true; return true;
}, },
[&](const ast::OverrideAttribute* override_deco) { [&](const ast::IdAttribute* override_deco) {
out << "override"; out << "id(" << override_deco->value << ")";
if (override_deco->has_value) {
out << "(" << override_deco->value << ")";
}
return true; return true;
}, },
[&](const ast::StructMemberSizeAttribute* size) { [&](const ast::StructMemberSizeAttribute* size) {

View File

@ -132,17 +132,17 @@ TEST_F(WgslGeneratorImplTest, Emit_Global_Texture) {
} }
TEST_F(WgslGeneratorImplTest, Emit_OverridableConstants) { TEST_F(WgslGeneratorImplTest, Emit_OverridableConstants) {
GlobalConst("a", ty.f32(), nullptr, {Override()}); Override("a", ty.f32(), nullptr);
GlobalConst("b", ty.f32(), nullptr, {Override(7u)}); Override("b", ty.f32(), nullptr, {Id(7u)});
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
gen.increment_indent(); gen.increment_indent();
ASSERT_TRUE(gen.Generate()) << gen.error(); ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"( @override let a : f32; EXPECT_EQ(gen.result(), R"( override a : f32;
@override(7) let b : f32; @id(7) override b : f32;
)"); )");
} }

View File

@ -14,7 +14,6 @@
#include <cstring> #include <cstring>
#include "src/ast/override_attribute.h"
#include "src/writer/wgsl/test_helper.h" #include "src/writer/wgsl/test_helper.h"
namespace tint { namespace tint {

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "src/ast/override_attribute.h"
#include "src/ast/struct_block_attribute.h" #include "src/ast/struct_block_attribute.h"
#include "src/writer/wgsl/test_helper.h" #include "src/writer/wgsl/test_helper.h"

View File

@ -171,6 +171,7 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../src/ast/function_test.cc", "../src/ast/function_test.cc",
"../src/ast/group_attribute_test.cc", "../src/ast/group_attribute_test.cc",
"../src/ast/i32_test.cc", "../src/ast/i32_test.cc",
"../src/ast/id_attribute_test.cc",
"../src/ast/identifier_expression_test.cc", "../src/ast/identifier_expression_test.cc",
"../src/ast/if_statement_test.cc", "../src/ast/if_statement_test.cc",
"../src/ast/index_accessor_expression_test.cc", "../src/ast/index_accessor_expression_test.cc",
@ -184,7 +185,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
"../src/ast/module_clone_test.cc", "../src/ast/module_clone_test.cc",
"../src/ast/module_test.cc", "../src/ast/module_test.cc",
"../src/ast/multisampled_texture_test.cc", "../src/ast/multisampled_texture_test.cc",
"../src/ast/override_attribute_test.cc",
"../src/ast/phony_expression_test.cc", "../src/ast/phony_expression_test.cc",
"../src/ast/pointer_test.cc", "../src/ast/pointer_test.cc",
"../src/ast/return_statement_test.cc", "../src/ast/return_statement_test.cc",

View File

@ -1,4 +1,4 @@
@override let o : bool; override o : bool;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : bool; override o : bool;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32; override o : f32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32; override o : f32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32; override o : i32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32; override o : i32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32; override o : u32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32; override o : u32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : bool = true; override o : bool = true;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : bool = true; override o : bool = true;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32 = 1.0; override o : f32 = 1.0;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32 = 1.0; override o : f32 = 1.0;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32 = 1; override o : i32 = 1;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32 = 1; override o : i32 = 1;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32 = 1u; override o : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32 = 1u; override o : u32 = 1u;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : bool = bool(); override o : bool = bool();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : bool = bool(); override o : bool = bool();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32 = f32(); override o : f32 = f32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : f32 = f32(); override o : f32 = f32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32 = i32(); override o : i32 = i32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : i32 = i32(); override o : i32 = i32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32 = u32(); override o : u32 = u32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override let o : u32 = u32(); override o : u32 = u32();
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : bool; @id(1234) override o : bool;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : bool; @id(1234) override o : bool;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : f32; @id(1234) override o : f32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : f32; @id(1234) override o : f32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : i32; @id(1234) override o : i32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : i32; @id(1234) override o : i32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : u32; @id(1234) override o : u32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : u32; @id(1234) override o : u32;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : bool = true; @id(1234) override o : bool = true;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : bool = true; @id(1234) override o : bool = true;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : f32 = 1.0; @id(1234) override o : f32 = 1.0;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : f32 = 1.0; @id(1234) override o : f32 = 1.0;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

View File

@ -1,4 +1,4 @@
@override(1234) let o : i32 = 1; @id(1234) override o : i32 = 1;
@stage(compute) @workgroup_size(1) @stage(compute) @workgroup_size(1)
fn main() { fn main() {

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