mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 08:27:05 +00:00
ast: Merge DecoratedVariable into Variable
Remove all Variable setters (with exception to set_storage_class() which is called by the TypeDeterminer) Bug: tint:390 Change-Id: I172667e21e2b02e85dcea6703aa1e608ec718250 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35015 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
ccc67252ff
commit
a80511e021
@@ -32,7 +32,16 @@ Builder::~Builder() = default;
|
||||
Variable* Builder::Var(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type) {
|
||||
auto* var = create<Variable>(Source{}, name, storage, type);
|
||||
return Var(name, storage, type, nullptr, {});
|
||||
}
|
||||
|
||||
Variable* Builder::Var(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations) {
|
||||
auto* var = create<Variable>(Source{}, name, storage, type, false,
|
||||
constructor, decorations);
|
||||
OnVariableBuilt(var);
|
||||
return var;
|
||||
}
|
||||
@@ -40,8 +49,16 @@ Variable* Builder::Var(const std::string& name,
|
||||
Variable* Builder::Const(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type) {
|
||||
auto* var = create<Variable>(Source{}, name, storage, type);
|
||||
var->set_is_const(true);
|
||||
return Const(name, storage, type, nullptr, {});
|
||||
}
|
||||
|
||||
Variable* Builder::Const(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations) {
|
||||
auto* var = create<Variable>(Source{}, name, storage, type, true, constructor,
|
||||
decorations);
|
||||
OnVariableBuilt(var);
|
||||
return var;
|
||||
}
|
||||
|
||||
@@ -428,7 +428,8 @@ class Builder {
|
||||
/// @param name the variable name
|
||||
/// @param storage the variable storage class
|
||||
/// @param type the variable type
|
||||
/// @returns a `Variable` with the given name, storage and type
|
||||
/// @returns a `Variable` with the given name, storage and type. The variable
|
||||
/// will be built with a nullptr constructor and no decorations.
|
||||
Variable* Var(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type);
|
||||
@@ -436,11 +437,36 @@ class Builder {
|
||||
/// @param name the variable name
|
||||
/// @param storage the variable storage class
|
||||
/// @param type the variable type
|
||||
/// @returns a constant `Variable` with the given name, storage and type
|
||||
/// @param constructor constructor expression
|
||||
/// @param decorations variable decorations
|
||||
/// @returns a `Variable` with the given name, storage and type
|
||||
Variable* Var(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations);
|
||||
|
||||
/// @param name the variable name
|
||||
/// @param storage the variable storage class
|
||||
/// @param type the variable type
|
||||
/// @returns a constant `Variable` with the given name, storage and type. The
|
||||
/// variable will be built with a nullptr constructor and no decorations.
|
||||
Variable* Const(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type);
|
||||
|
||||
/// @param name the variable name
|
||||
/// @param storage the variable storage class
|
||||
/// @param type the variable type
|
||||
/// @param constructor optional constructor expression
|
||||
/// @param decorations optional variable decorations
|
||||
/// @returns a constant `Variable` with the given name, storage and type
|
||||
Variable* Const(const std::string& name,
|
||||
StorageClass storage,
|
||||
type::Type* type,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations);
|
||||
|
||||
/// @param func the function name
|
||||
/// @param args the function call arguments
|
||||
/// @returns a `CallExpression` to the function `func`, with the
|
||||
|
||||
@@ -1,116 +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/decorated_variable.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "src/ast/builtin_decoration.h"
|
||||
#include "src/ast/clone_context.h"
|
||||
#include "src/ast/constant_id_decoration.h"
|
||||
#include "src/ast/location_decoration.h"
|
||||
#include "src/ast/module.h"
|
||||
|
||||
TINT_INSTANTIATE_CLASS_ID(tint::ast::DecoratedVariable);
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
DecoratedVariable::DecoratedVariable() = default;
|
||||
|
||||
DecoratedVariable::DecoratedVariable(Variable* var)
|
||||
: Base(var->source(), var->name(), var->storage_class(), var->type()) {}
|
||||
|
||||
DecoratedVariable::DecoratedVariable(DecoratedVariable&&) = default;
|
||||
|
||||
DecoratedVariable::~DecoratedVariable() = default;
|
||||
|
||||
bool DecoratedVariable::HasLocationDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<LocationDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DecoratedVariable::HasBuiltinDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<BuiltinDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DecoratedVariable::HasConstantIdDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<ConstantIdDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t DecoratedVariable::constant_id() const {
|
||||
assert(HasConstantIdDecoration());
|
||||
for (auto* deco : decorations_) {
|
||||
if (auto* cid = deco->As<ConstantIdDecoration>()) {
|
||||
return cid->value();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DecoratedVariable* DecoratedVariable::Clone(CloneContext* ctx) const {
|
||||
auto* cloned = ctx->mod->create<DecoratedVariable>();
|
||||
cloned->set_source(ctx->Clone(source()));
|
||||
cloned->set_name(name());
|
||||
cloned->set_storage_class(storage_class());
|
||||
cloned->set_type(ctx->Clone(type()));
|
||||
cloned->set_constructor(ctx->Clone(constructor()));
|
||||
cloned->set_is_const(is_const());
|
||||
cloned->set_decorations(ctx->Clone(decorations()));
|
||||
return cloned;
|
||||
}
|
||||
|
||||
bool DecoratedVariable::IsValid() const {
|
||||
return Variable::IsValid();
|
||||
}
|
||||
|
||||
void DecoratedVariable::to_str(std::ostream& out, size_t indent) const {
|
||||
make_indent(out, indent);
|
||||
out << "DecoratedVariable";
|
||||
if (is_const()) {
|
||||
out << "Const";
|
||||
}
|
||||
out << "{" << std::endl;
|
||||
|
||||
make_indent(out, indent + 2);
|
||||
out << "Decorations{" << std::endl;
|
||||
for (auto* deco : decorations_) {
|
||||
deco->to_str(out, indent + 4);
|
||||
}
|
||||
|
||||
make_indent(out, indent + 2);
|
||||
out << "}" << std::endl;
|
||||
|
||||
info_to_str(out, indent + 2);
|
||||
constructor_to_str(out, indent + 2);
|
||||
make_indent(out, indent);
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
@@ -1,84 +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.
|
||||
|
||||
#ifndef SRC_AST_DECORATED_VARIABLE_H_
|
||||
#define SRC_AST_DECORATED_VARIABLE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// A Decorated Variable statement.
|
||||
class DecoratedVariable : public Castable<DecoratedVariable, Variable> {
|
||||
public:
|
||||
/// Create a new empty decorated variable statement
|
||||
/// Note, used by the `Clone` method.
|
||||
DecoratedVariable();
|
||||
/// Create a decorated variable from an existing variable
|
||||
/// @param var the variable to initialize from
|
||||
explicit DecoratedVariable(Variable* var);
|
||||
/// Move constructor
|
||||
DecoratedVariable(DecoratedVariable&&);
|
||||
|
||||
~DecoratedVariable() override;
|
||||
|
||||
/// Sets a decoration to the variable
|
||||
/// @param decos the decorations to set
|
||||
void set_decorations(VariableDecorationList decos) {
|
||||
decorations_ = std::move(decos);
|
||||
}
|
||||
/// @returns the decorations attached to this variable
|
||||
const VariableDecorationList& decorations() const { return decorations_; }
|
||||
|
||||
/// @returns true if the decorations include a LocationDecoration
|
||||
bool HasLocationDecoration() const;
|
||||
/// @returns true if the deocrations include a BuiltinDecoration
|
||||
bool HasBuiltinDecoration() const;
|
||||
/// @returns true if the decorations include a ConstantIdDecoration
|
||||
bool HasConstantIdDecoration() const;
|
||||
|
||||
/// @returns the constant_id value for the variable. Assumes that
|
||||
/// HasConstantIdDecoration() has been called first.
|
||||
uint32_t constant_id() const;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @note Semantic information such as resolved expression type and intrinsic
|
||||
/// information is not cloned.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
DecoratedVariable* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// @returns true if the name and path are both present
|
||||
bool IsValid() const override;
|
||||
|
||||
/// @param out the stream to write to
|
||||
/// @param indent number of spaces to indent the node when writing
|
||||
void to_str(std::ostream& out, size_t indent) const override;
|
||||
|
||||
private:
|
||||
DecoratedVariable(const DecoratedVariable&) = delete;
|
||||
|
||||
VariableDecorationList decorations_;
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_DECORATED_VARIABLE_H_
|
||||
@@ -1,146 +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/decorated_variable.h"
|
||||
|
||||
#include "src/ast/binding_decoration.h"
|
||||
#include "src/ast/builtin_decoration.h"
|
||||
#include "src/ast/constant_id_decoration.h"
|
||||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/location_decoration.h"
|
||||
#include "src/ast/set_decoration.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
#include "src/ast/type/f32_type.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace {
|
||||
|
||||
using DecoratedVariableTest = TestHelper;
|
||||
|
||||
TEST_F(DecoratedVariableTest, Creation) {
|
||||
type::I32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
DecoratedVariable dv(var);
|
||||
|
||||
EXPECT_EQ(dv.name(), "my_var");
|
||||
EXPECT_EQ(dv.storage_class(), StorageClass::kFunction);
|
||||
EXPECT_EQ(dv.type(), &t);
|
||||
EXPECT_EQ(dv.source().range.begin.line, 0u);
|
||||
EXPECT_EQ(dv.source().range.begin.column, 0u);
|
||||
EXPECT_EQ(dv.source().range.end.line, 0u);
|
||||
EXPECT_EQ(dv.source().range.end.column, 0u);
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, CreationWithSource) {
|
||||
Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}};
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(s, "i", StorageClass::kPrivate, &t);
|
||||
DecoratedVariable dv(var);
|
||||
|
||||
EXPECT_EQ(dv.name(), "i");
|
||||
EXPECT_EQ(dv.storage_class(), StorageClass::kPrivate);
|
||||
EXPECT_EQ(dv.type(), &t);
|
||||
EXPECT_EQ(dv.source().range.begin.line, 27u);
|
||||
EXPECT_EQ(dv.source().range.begin.column, 4u);
|
||||
EXPECT_EQ(dv.source().range.end.line, 27u);
|
||||
EXPECT_EQ(dv.source().range.end.column, 5u);
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, NoDecorations) {
|
||||
type::I32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
DecoratedVariable dv(var);
|
||||
EXPECT_FALSE(dv.HasLocationDecoration());
|
||||
EXPECT_FALSE(dv.HasBuiltinDecoration());
|
||||
EXPECT_FALSE(dv.HasConstantIdDecoration());
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, WithDecorations) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
DecoratedVariable dv(var);
|
||||
|
||||
VariableDecorationList decos;
|
||||
decos.push_back(create<LocationDecoration>(1, Source{}));
|
||||
decos.push_back(create<BuiltinDecoration>(Builtin::kPosition, Source{}));
|
||||
decos.push_back(create<ConstantIdDecoration>(1200, Source{}));
|
||||
|
||||
dv.set_decorations(decos);
|
||||
|
||||
EXPECT_TRUE(dv.HasLocationDecoration());
|
||||
EXPECT_TRUE(dv.HasBuiltinDecoration());
|
||||
EXPECT_TRUE(dv.HasConstantIdDecoration());
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, ConstantId) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
DecoratedVariable dv(var);
|
||||
|
||||
VariableDecorationList decos;
|
||||
decos.push_back(create<ConstantIdDecoration>(1200, Source{}));
|
||||
dv.set_decorations(decos);
|
||||
|
||||
EXPECT_EQ(dv.constant_id(), 1200u);
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, IsValid) {
|
||||
type::I32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kNone, &t);
|
||||
DecoratedVariable dv(var);
|
||||
EXPECT_TRUE(dv.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, IsDecorated) {
|
||||
type::I32 t;
|
||||
DecoratedVariable dv(
|
||||
create<Variable>(Source{}, "my_var", StorageClass::kNone, &t));
|
||||
EXPECT_TRUE(dv.Is<DecoratedVariable>());
|
||||
}
|
||||
|
||||
TEST_F(DecoratedVariableTest, to_str) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
DecoratedVariable dv(var);
|
||||
dv.set_constructor(create<IdentifierExpression>("expr"));
|
||||
|
||||
VariableDecorationList decos;
|
||||
decos.push_back(create<BindingDecoration>(2, Source{}));
|
||||
decos.push_back(create<SetDecoration>(1, Source{}));
|
||||
|
||||
dv.set_decorations(decos);
|
||||
std::ostringstream out;
|
||||
dv.to_str(out, 2);
|
||||
EXPECT_EQ(out.str(), R"( DecoratedVariable{
|
||||
Decorations{
|
||||
BindingDecoration{2}
|
||||
SetDecoration{1}
|
||||
}
|
||||
my_var
|
||||
function
|
||||
__f32
|
||||
{
|
||||
Identifier[not set]{expr}
|
||||
}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
@@ -17,12 +17,12 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "src/ast/clone_context.h"
|
||||
#include "src/ast/decorated_variable.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/stage_decoration.h"
|
||||
#include "src/ast/type/multisampled_texture_type.h"
|
||||
#include "src/ast/type/sampled_texture_type.h"
|
||||
#include "src/ast/type/texture_type.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/workgroup_decoration.h"
|
||||
|
||||
TINT_INSTANTIATE_CLASS_ID(tint::ast::Function);
|
||||
@@ -88,12 +88,10 @@ Function::referenced_location_variables() const {
|
||||
std::vector<std::pair<Variable*, LocationDecoration*>> ret;
|
||||
|
||||
for (auto* var : referenced_module_variables()) {
|
||||
if (auto* decos = var->As<DecoratedVariable>()) {
|
||||
for (auto* deco : decos->decorations()) {
|
||||
if (auto* location = deco->As<LocationDecoration>()) {
|
||||
ret.push_back({var, location});
|
||||
break;
|
||||
}
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* location = deco->As<LocationDecoration>()) {
|
||||
ret.push_back({var, location});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,22 +107,20 @@ Function::referenced_uniform_variables() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -138,22 +134,20 @@ Function::referenced_storagebuffer_variables() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -163,12 +157,10 @@ Function::referenced_builtin_variables() const {
|
||||
std::vector<std::pair<Variable*, BuiltinDecoration*>> ret;
|
||||
|
||||
for (auto* var : referenced_module_variables()) {
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* builtin = deco->As<BuiltinDecoration>()) {
|
||||
ret.push_back({var, builtin});
|
||||
break;
|
||||
}
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* builtin = deco->As<BuiltinDecoration>()) {
|
||||
ret.push_back({var, builtin});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,12 +192,10 @@ Function::local_referenced_builtin_variables() const {
|
||||
std::vector<std::pair<Variable*, BuiltinDecoration*>> ret;
|
||||
|
||||
for (auto* var : local_referenced_module_variables()) {
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* builtin = deco->As<BuiltinDecoration>()) {
|
||||
ret.push_back({var, builtin});
|
||||
break;
|
||||
}
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* builtin = deco->As<BuiltinDecoration>()) {
|
||||
ret.push_back({var, builtin});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,23 +304,21 @@ Function::ReferencedSamplerVariablesImpl(type::SamplerKind kind) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
}
|
||||
if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -353,22 +341,20 @@ Function::ReferencedSampledTextureVariablesImpl(bool multisampled) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto* decorated = var->As<DecoratedVariable>()) {
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : decorated->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
BindingDecoration* binding = nullptr;
|
||||
SetDecoration* set = nullptr;
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (auto* b = deco->As<BindingDecoration>()) {
|
||||
binding = b;
|
||||
} else if (auto* s = deco->As<SetDecoration>()) {
|
||||
set = s;
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
if (binding == nullptr || set == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push_back({var, BindingInfo{binding, set}});
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "src/ast/function.h"
|
||||
|
||||
#include "src/ast/builtin_decoration.h"
|
||||
#include "src/ast/decorated_variable.h"
|
||||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/location_decoration.h"
|
||||
#include "src/ast/pipeline_stage.h"
|
||||
@@ -37,8 +36,9 @@ TEST_F(FunctionTest, Creation) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
auto* var = params[0];
|
||||
|
||||
Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
|
||||
@@ -54,8 +54,9 @@ TEST_F(FunctionTest, Creation_WithSource) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
Function f(Source{Source::Location{20, 2}}, "func", params, &void_type,
|
||||
create<BlockStatement>(), FunctionDecorationList{});
|
||||
@@ -68,7 +69,8 @@ TEST_F(FunctionTest, AddDuplicateReferencedVariables) {
|
||||
type::Void void_type;
|
||||
type::I32 i32;
|
||||
|
||||
Variable v(Source{}, "var", StorageClass::kInput, &i32);
|
||||
Variable v(Source{}, "var", StorageClass::kInput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{});
|
||||
Function f(Source{}, "func", VariableList{}, &void_type,
|
||||
create<BlockStatement>(), FunctionDecorationList{});
|
||||
|
||||
@@ -79,7 +81,8 @@ TEST_F(FunctionTest, AddDuplicateReferencedVariables) {
|
||||
f.add_referenced_module_variable(&v);
|
||||
ASSERT_EQ(f.referenced_module_variables().size(), 1u);
|
||||
|
||||
Variable v2(Source{}, "var2", StorageClass::kOutput, &i32);
|
||||
Variable v2(Source{}, "var2", StorageClass::kOutput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{});
|
||||
f.add_referenced_module_variable(&v2);
|
||||
ASSERT_EQ(f.referenced_module_variables().size(), 2u);
|
||||
EXPECT_EQ(f.referenced_module_variables()[1], &v2);
|
||||
@@ -89,38 +92,44 @@ TEST_F(FunctionTest, GetReferenceLocations) {
|
||||
type::Void void_type;
|
||||
type::I32 i32;
|
||||
|
||||
DecoratedVariable loc1(
|
||||
create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32));
|
||||
loc1.set_decorations({create<LocationDecoration>(0, Source{})});
|
||||
auto* loc1 = create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<LocationDecoration>(0, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable loc2(
|
||||
create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32));
|
||||
loc2.set_decorations({create<LocationDecoration>(1, Source{})});
|
||||
auto* loc2 = create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<LocationDecoration>(1, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable builtin1(
|
||||
create<Variable>(Source{}, "builtin1", StorageClass::kInput, &i32));
|
||||
builtin1.set_decorations(
|
||||
{create<BuiltinDecoration>(Builtin::kPosition, Source{})});
|
||||
auto* builtin1 = create<Variable>(
|
||||
Source{}, "builtin1", StorageClass::kInput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<BuiltinDecoration>(Builtin::kPosition, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable builtin2(
|
||||
create<Variable>(Source{}, "builtin2", StorageClass::kInput, &i32));
|
||||
builtin2.set_decorations(
|
||||
{create<BuiltinDecoration>(Builtin::kFragDepth, Source{})});
|
||||
auto* builtin2 = create<Variable>(
|
||||
Source{}, "builtin2", StorageClass::kInput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<BuiltinDecoration>(Builtin::kFragDepth, Source{}),
|
||||
});
|
||||
|
||||
Function f(Source{}, "func", VariableList{}, &void_type,
|
||||
create<BlockStatement>(), FunctionDecorationList{});
|
||||
|
||||
f.add_referenced_module_variable(&loc1);
|
||||
f.add_referenced_module_variable(&builtin1);
|
||||
f.add_referenced_module_variable(&loc2);
|
||||
f.add_referenced_module_variable(&builtin2);
|
||||
f.add_referenced_module_variable(loc1);
|
||||
f.add_referenced_module_variable(builtin1);
|
||||
f.add_referenced_module_variable(loc2);
|
||||
f.add_referenced_module_variable(builtin2);
|
||||
ASSERT_EQ(f.referenced_module_variables().size(), 4u);
|
||||
|
||||
auto ref_locs = f.referenced_location_variables();
|
||||
ASSERT_EQ(ref_locs.size(), 2u);
|
||||
EXPECT_EQ(ref_locs[0].first, &loc1);
|
||||
EXPECT_EQ(ref_locs[0].first, loc1);
|
||||
EXPECT_EQ(ref_locs[0].second->value(), 0u);
|
||||
EXPECT_EQ(ref_locs[1].first, &loc2);
|
||||
EXPECT_EQ(ref_locs[1].first, loc2);
|
||||
EXPECT_EQ(ref_locs[1].second->value(), 1u);
|
||||
}
|
||||
|
||||
@@ -128,38 +137,44 @@ TEST_F(FunctionTest, GetReferenceBuiltins) {
|
||||
type::Void void_type;
|
||||
type::I32 i32;
|
||||
|
||||
DecoratedVariable loc1(
|
||||
create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32));
|
||||
loc1.set_decorations({create<LocationDecoration>(0, Source{})});
|
||||
auto* loc1 = create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<LocationDecoration>(0, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable loc2(
|
||||
create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32));
|
||||
loc2.set_decorations({create<LocationDecoration>(1, Source{})});
|
||||
auto* loc2 = create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<LocationDecoration>(1, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable builtin1(
|
||||
create<Variable>(Source{}, "builtin1", StorageClass::kInput, &i32));
|
||||
builtin1.set_decorations(
|
||||
{create<BuiltinDecoration>(Builtin::kPosition, Source{})});
|
||||
auto* builtin1 = create<Variable>(
|
||||
Source{}, "builtin1", StorageClass::kInput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<BuiltinDecoration>(Builtin::kPosition, Source{}),
|
||||
});
|
||||
|
||||
DecoratedVariable builtin2(
|
||||
create<Variable>(Source{}, "builtin2", StorageClass::kInput, &i32));
|
||||
builtin2.set_decorations(
|
||||
{create<BuiltinDecoration>(Builtin::kFragDepth, Source{})});
|
||||
auto* builtin2 = create<Variable>(
|
||||
Source{}, "builtin2", StorageClass::kInput, &i32, false, nullptr,
|
||||
ast::VariableDecorationList{
|
||||
create<BuiltinDecoration>(Builtin::kFragDepth, Source{}),
|
||||
});
|
||||
|
||||
Function f(Source{}, "func", VariableList{}, &void_type,
|
||||
create<BlockStatement>(), FunctionDecorationList{});
|
||||
|
||||
f.add_referenced_module_variable(&loc1);
|
||||
f.add_referenced_module_variable(&builtin1);
|
||||
f.add_referenced_module_variable(&loc2);
|
||||
f.add_referenced_module_variable(&builtin2);
|
||||
f.add_referenced_module_variable(loc1);
|
||||
f.add_referenced_module_variable(builtin1);
|
||||
f.add_referenced_module_variable(loc2);
|
||||
f.add_referenced_module_variable(builtin2);
|
||||
ASSERT_EQ(f.referenced_module_variables().size(), 4u);
|
||||
|
||||
auto ref_locs = f.referenced_builtin_variables();
|
||||
ASSERT_EQ(ref_locs.size(), 2u);
|
||||
EXPECT_EQ(ref_locs[0].first, &builtin1);
|
||||
EXPECT_EQ(ref_locs[0].first, builtin1);
|
||||
EXPECT_EQ(ref_locs[0].second->value(), Builtin::kPosition);
|
||||
EXPECT_EQ(ref_locs[1].first, &builtin2);
|
||||
EXPECT_EQ(ref_locs[1].first, builtin2);
|
||||
EXPECT_EQ(ref_locs[1].second->value(), Builtin::kFragDepth);
|
||||
}
|
||||
|
||||
@@ -182,8 +197,9 @@ TEST_F(FunctionTest, IsValid) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
auto* body = create<BlockStatement>();
|
||||
body->append(create<DiscardStatement>());
|
||||
@@ -198,8 +214,9 @@ TEST_F(FunctionTest, IsValid_EmptyName) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
Function f(Source{}, "", params, &void_type, create<BlockStatement>(),
|
||||
FunctionDecorationList{});
|
||||
@@ -210,8 +227,9 @@ TEST_F(FunctionTest, IsValid_MissingReturnType) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
Function f(Source{}, "func", params, nullptr, create<BlockStatement>(),
|
||||
FunctionDecorationList{});
|
||||
@@ -223,8 +241,9 @@ TEST_F(FunctionTest, IsValid_NullParam) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
params.push_back(nullptr);
|
||||
|
||||
Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
|
||||
@@ -236,8 +255,9 @@ TEST_F(FunctionTest, IsValid_InvalidParam) {
|
||||
type::Void void_type;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, nullptr));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone,
|
||||
nullptr, false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
|
||||
FunctionDecorationList{});
|
||||
@@ -249,8 +269,9 @@ TEST_F(FunctionTest, IsValid_NullBodyStatement) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
auto* body = create<BlockStatement>();
|
||||
body->append(create<DiscardStatement>());
|
||||
@@ -267,8 +288,9 @@ TEST_F(FunctionTest, IsValid_InvalidBodyStatement) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
auto* body = create<BlockStatement>();
|
||||
body->append(create<DiscardStatement>());
|
||||
@@ -325,8 +347,9 @@ TEST_F(FunctionTest, ToStr_WithParams) {
|
||||
type::I32 i32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
|
||||
params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
auto* body = create<BlockStatement>();
|
||||
body->append(create<DiscardStatement>());
|
||||
@@ -364,10 +387,12 @@ TEST_F(FunctionTest, TypeName_WithParams) {
|
||||
type::F32 f32;
|
||||
|
||||
VariableList params;
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var1", StorageClass::kNone, &i32));
|
||||
params.push_back(
|
||||
create<Variable>(Source{}, "var2", StorageClass::kNone, &f32));
|
||||
params.push_back(create<Variable>(Source{}, "var1", StorageClass::kNone, &i32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
params.push_back(create<Variable>(Source{}, "var2", StorageClass::kNone, &f32,
|
||||
false, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
|
||||
Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
|
||||
FunctionDecorationList{});
|
||||
|
||||
@@ -67,7 +67,8 @@ TEST_F(ModuleTest, IsValid_Empty) {
|
||||
|
||||
TEST_F(ModuleTest, IsValid_GlobalVariable) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, &f32);
|
||||
auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, &f32,
|
||||
false, nullptr, ast::VariableDecorationList{});
|
||||
|
||||
Module m;
|
||||
m.AddGlobalVariable(var);
|
||||
@@ -81,7 +82,8 @@ TEST_F(ModuleTest, IsValid_Null_GlobalVariable) {
|
||||
}
|
||||
|
||||
TEST_F(ModuleTest, IsValid_Invalid_GlobalVariable) {
|
||||
auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, nullptr);
|
||||
auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, nullptr,
|
||||
false, nullptr, ast::VariableDecorationList{});
|
||||
|
||||
Module m;
|
||||
m.AddGlobalVariable(var);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "src/ast/clone_context.h"
|
||||
#include "src/ast/decorated_variable.h"
|
||||
#include "src/ast/constant_id_decoration.h"
|
||||
#include "src/ast/module.h"
|
||||
|
||||
TINT_INSTANTIATE_CLASS_ID(tint::ast::Variable);
|
||||
@@ -25,24 +25,66 @@ TINT_INSTANTIATE_CLASS_ID(tint::ast::Variable);
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
Variable::Variable() = default;
|
||||
|
||||
Variable::Variable(const Source& source,
|
||||
const std::string& name,
|
||||
StorageClass sc,
|
||||
type::Type* type)
|
||||
: Base(source), name_(name), storage_class_(sc), type_(type) {}
|
||||
type::Type* type,
|
||||
bool is_const,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations)
|
||||
: Base(source),
|
||||
name_(name),
|
||||
storage_class_(sc),
|
||||
type_(type),
|
||||
is_const_(is_const),
|
||||
constructor_(constructor),
|
||||
decorations_(std::move(decorations)) {}
|
||||
|
||||
Variable::Variable(Variable&&) = default;
|
||||
|
||||
Variable::~Variable() = default;
|
||||
|
||||
bool Variable::HasLocationDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<LocationDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Variable::HasBuiltinDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<BuiltinDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Variable::HasConstantIdDecoration() const {
|
||||
for (auto* deco : decorations_) {
|
||||
if (deco->Is<ConstantIdDecoration>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t Variable::constant_id() const {
|
||||
assert(HasConstantIdDecoration());
|
||||
for (auto* deco : decorations_) {
|
||||
if (auto* cid = deco->As<ConstantIdDecoration>()) {
|
||||
return cid->value();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Variable* Variable::Clone(CloneContext* ctx) const {
|
||||
auto* cloned = ctx->mod->create<Variable>(
|
||||
ctx->Clone(source()), name(), storage_class(), ctx->Clone(type()));
|
||||
cloned->set_constructor(ctx->Clone(constructor()));
|
||||
cloned->set_is_const(is_const());
|
||||
return cloned;
|
||||
return ctx->mod->create<Variable>(
|
||||
ctx->Clone(source()), name(), storage_class(), ctx->Clone(type()),
|
||||
is_const_, ctx->Clone(constructor()), ctx->Clone(decorations_));
|
||||
}
|
||||
|
||||
bool Variable::IsValid() const {
|
||||
@@ -87,6 +129,17 @@ void Variable::to_str(std::ostream& out, size_t indent) const {
|
||||
out << "Const";
|
||||
}
|
||||
out << "{" << std::endl;
|
||||
|
||||
if (!decorations_.empty()) {
|
||||
make_indent(out, indent + 2);
|
||||
out << "Decorations{" << std::endl;
|
||||
for (auto* deco : decorations_) {
|
||||
deco->to_str(out, indent + 4);
|
||||
}
|
||||
make_indent(out, indent + 2);
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
info_to_str(out, indent + 2);
|
||||
constructor_to_str(out, indent + 2);
|
||||
make_indent(out, indent);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "src/ast/node.h"
|
||||
#include "src/ast/storage_class.h"
|
||||
#include "src/ast/type/type.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
@@ -83,25 +84,24 @@ class Variable : public Castable<Variable, Node> {
|
||||
/// @param name the variables name
|
||||
/// @param sc the variable storage class
|
||||
/// @param type the value type
|
||||
/// @param is_const true if the variable is const
|
||||
/// @param constructor the constructor expression
|
||||
/// @param decorations the variable decorations
|
||||
Variable(const Source& source,
|
||||
const std::string& name,
|
||||
StorageClass sc,
|
||||
type::Type* type);
|
||||
type::Type* type,
|
||||
bool is_const,
|
||||
Expression* constructor,
|
||||
VariableDecorationList decorations);
|
||||
/// Move constructor
|
||||
Variable(Variable&&);
|
||||
|
||||
~Variable() override;
|
||||
|
||||
/// Sets the variable name
|
||||
/// @param name the name to set
|
||||
void set_name(const std::string& name) { name_ = name; }
|
||||
/// @returns the variable name
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
/// Sets the value type if a const or formal parameter, or the
|
||||
/// store type if a var.
|
||||
/// @param type the type
|
||||
void set_type(type::Type* type) { type_ = type; }
|
||||
/// @returns the variable's type.
|
||||
type::Type* type() const { return type_; }
|
||||
|
||||
@@ -111,20 +111,28 @@ class Variable : public Castable<Variable, Node> {
|
||||
/// @returns the storage class
|
||||
StorageClass storage_class() const { return storage_class_; }
|
||||
|
||||
/// Sets the constructor
|
||||
/// @param expr the constructor expression
|
||||
void set_constructor(Expression* expr) { constructor_ = expr; }
|
||||
/// @returns the constructor expression or nullptr if none set
|
||||
Expression* constructor() const { return constructor_; }
|
||||
/// @returns true if the variable has an constructor
|
||||
bool has_constructor() const { return constructor_ != nullptr; }
|
||||
|
||||
/// Sets if the variable is constant
|
||||
/// @param val the value to be set
|
||||
void set_is_const(bool val) { is_const_ = val; }
|
||||
/// @returns true if this is a constant, false otherwise
|
||||
bool is_const() const { return is_const_; }
|
||||
|
||||
/// @returns the decorations attached to this variable
|
||||
const VariableDecorationList& decorations() const { return decorations_; }
|
||||
|
||||
/// @returns true if the decorations include a LocationDecoration
|
||||
bool HasLocationDecoration() const;
|
||||
/// @returns true if the deocrations include a BuiltinDecoration
|
||||
bool HasBuiltinDecoration() const;
|
||||
/// @returns true if the decorations include a ConstantIdDecoration
|
||||
bool HasConstantIdDecoration() const;
|
||||
|
||||
/// @returns the constant_id value for the variable. Assumes that
|
||||
/// HasConstantIdDecoration() has been called first.
|
||||
uint32_t constant_id() const;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @note Semantic information such as resolved expression type and intrinsic
|
||||
@@ -142,10 +150,6 @@ class Variable : public Castable<Variable, Node> {
|
||||
void to_str(std::ostream& out, size_t indent) const override;
|
||||
|
||||
protected:
|
||||
/// Constructor
|
||||
/// Used by the DecoratedVariable constructor.
|
||||
Variable();
|
||||
|
||||
/// Output information for this variable.
|
||||
/// @param out the stream to write to
|
||||
/// @param indent number of spaces to indent the node when writing
|
||||
@@ -158,12 +162,13 @@ class Variable : public Castable<Variable, Node> {
|
||||
private:
|
||||
Variable(const Variable&) = delete;
|
||||
|
||||
bool is_const_ = false;
|
||||
std::string name_;
|
||||
StorageClass storage_class_ = StorageClass::kNone;
|
||||
// The value type if a const or formal paramter, and the store type if a var
|
||||
type::Type* type_ = nullptr;
|
||||
bool is_const_ = false;
|
||||
Expression* constructor_ = nullptr;
|
||||
VariableDecorationList decorations_;
|
||||
};
|
||||
|
||||
/// A list of variables
|
||||
|
||||
@@ -26,7 +26,8 @@ using VariableDeclStatementTest = TestHelper;
|
||||
|
||||
TEST_F(VariableDeclStatementTest, Creation) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
|
||||
VariableDeclStatement stmt(var);
|
||||
EXPECT_EQ(stmt.variable(), var);
|
||||
@@ -34,7 +35,8 @@ TEST_F(VariableDeclStatementTest, Creation) {
|
||||
|
||||
TEST_F(VariableDeclStatementTest, Creation_WithSource) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
|
||||
VariableDeclStatement stmt(Source{Source::Location{20, 2}}, var);
|
||||
auto src = stmt.source();
|
||||
@@ -44,7 +46,8 @@ TEST_F(VariableDeclStatementTest, Creation_WithSource) {
|
||||
|
||||
TEST_F(VariableDeclStatementTest, IsVariableDecl) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
|
||||
VariableDeclStatement s(var);
|
||||
EXPECT_TRUE(s.Is<VariableDeclStatement>());
|
||||
@@ -52,14 +55,16 @@ TEST_F(VariableDeclStatementTest, IsVariableDecl) {
|
||||
|
||||
TEST_F(VariableDeclStatementTest, IsValid) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
VariableDeclStatement stmt(var);
|
||||
EXPECT_TRUE(stmt.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableDeclStatementTest, IsValid_InvalidVariable) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
VariableDeclStatement stmt(var);
|
||||
EXPECT_FALSE(stmt.IsValid());
|
||||
}
|
||||
@@ -71,7 +76,8 @@ TEST_F(VariableDeclStatementTest, IsValid_NullVariable) {
|
||||
|
||||
TEST_F(VariableDeclStatementTest, ToStr) {
|
||||
type::F32 f32;
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32);
|
||||
auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
|
||||
nullptr, ast::VariableDecorationList{});
|
||||
|
||||
VariableDeclStatement stmt(Source{Source::Location{20, 2}}, var);
|
||||
std::ostringstream out;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "src/ast/variable.h"
|
||||
|
||||
#include "src/ast/constant_id_decoration.h"
|
||||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
#include "src/ast/type/f32_type.h"
|
||||
@@ -27,7 +28,8 @@ using VariableTest = TestHelper;
|
||||
|
||||
TEST_F(VariableTest, Creation) {
|
||||
type::I32 t;
|
||||
Variable v(Source{}, "my_var", StorageClass::kFunction, &t);
|
||||
Variable v(Source{}, "my_var", StorageClass::kFunction, &t, false, nullptr,
|
||||
ast::VariableDecorationList{});
|
||||
|
||||
EXPECT_EQ(v.name(), "my_var");
|
||||
EXPECT_EQ(v.storage_class(), StorageClass::kFunction);
|
||||
@@ -41,7 +43,8 @@ TEST_F(VariableTest, Creation) {
|
||||
TEST_F(VariableTest, CreationWithSource) {
|
||||
Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}};
|
||||
type::F32 t;
|
||||
Variable v(s, "i", StorageClass::kPrivate, &t);
|
||||
Variable v(s, "i", StorageClass::kPrivate, &t, false, nullptr,
|
||||
ast::VariableDecorationList{});
|
||||
|
||||
EXPECT_EQ(v.name(), "i");
|
||||
EXPECT_EQ(v.storage_class(), StorageClass::kPrivate);
|
||||
@@ -55,7 +58,8 @@ TEST_F(VariableTest, CreationWithSource) {
|
||||
TEST_F(VariableTest, CreationEmpty) {
|
||||
type::I32 t;
|
||||
Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}};
|
||||
Variable v(s, "a_var", StorageClass::kWorkgroup, &t);
|
||||
Variable v(s, "a_var", StorageClass::kWorkgroup, &t, false, nullptr,
|
||||
ast::VariableDecorationList{});
|
||||
|
||||
EXPECT_EQ(v.name(), "a_var");
|
||||
EXPECT_EQ(v.storage_class(), StorageClass::kWorkgroup);
|
||||
@@ -68,43 +72,58 @@ TEST_F(VariableTest, CreationEmpty) {
|
||||
|
||||
TEST_F(VariableTest, IsValid) {
|
||||
type::I32 t;
|
||||
Variable v{Source{}, "my_var", StorageClass::kNone, &t};
|
||||
Variable v{Source{}, "my_var", StorageClass::kNone, &t,
|
||||
false, nullptr, ast::VariableDecorationList{}};
|
||||
EXPECT_TRUE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, IsValid_WithConstructor) {
|
||||
type::I32 t;
|
||||
Variable v{Source{}, "my_var", StorageClass::kNone, &t};
|
||||
v.set_constructor(create<IdentifierExpression>("ident"));
|
||||
Variable v{Source{},
|
||||
"my_var",
|
||||
StorageClass::kNone,
|
||||
&t,
|
||||
false,
|
||||
create<IdentifierExpression>("ident"),
|
||||
ast::VariableDecorationList{}};
|
||||
EXPECT_TRUE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, IsValid_MissinName) {
|
||||
type::I32 t;
|
||||
Variable v{Source{}, "", StorageClass::kNone, &t};
|
||||
Variable v{Source{}, "", StorageClass::kNone, &t,
|
||||
false, nullptr, ast::VariableDecorationList{}};
|
||||
EXPECT_FALSE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, IsValid_MissingType) {
|
||||
Variable v{Source{}, "x", StorageClass::kNone, nullptr};
|
||||
Variable v{Source{}, "x", StorageClass::kNone, nullptr,
|
||||
false, nullptr, ast::VariableDecorationList{}};
|
||||
EXPECT_FALSE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, IsValid_MissingBoth) {
|
||||
Variable v{Source{}, "", StorageClass::kNone, nullptr};
|
||||
Variable v{Source{}, "", StorageClass::kNone, nullptr,
|
||||
false, nullptr, ast::VariableDecorationList{}};
|
||||
EXPECT_FALSE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, IsValid_InvalidConstructor) {
|
||||
type::I32 t;
|
||||
Variable v{Source{}, "my_var", StorageClass::kNone, &t};
|
||||
v.set_constructor(create<IdentifierExpression>(""));
|
||||
Variable v{Source{},
|
||||
"my_var",
|
||||
StorageClass::kNone,
|
||||
&t,
|
||||
false,
|
||||
create<IdentifierExpression>(""),
|
||||
ast::VariableDecorationList{}};
|
||||
EXPECT_FALSE(v.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, to_str) {
|
||||
type::F32 t;
|
||||
Variable v{Source{}, "my_var", StorageClass::kFunction, &t};
|
||||
Variable v{Source{}, "my_var", StorageClass::kFunction, &t,
|
||||
false, nullptr, ast::VariableDecorationList{}};
|
||||
std::ostringstream out;
|
||||
v.to_str(out, 2);
|
||||
EXPECT_EQ(out.str(), R"( Variable{
|
||||
@@ -115,6 +134,58 @@ TEST_F(VariableTest, to_str) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, WithDecorations) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(
|
||||
Source{}, "my_var", StorageClass::kFunction, &t, false, nullptr,
|
||||
VariableDecorationList{
|
||||
create<LocationDecoration>(1, Source{}),
|
||||
create<BuiltinDecoration>(Builtin::kPosition, Source{}),
|
||||
create<ConstantIdDecoration>(1200, Source{}),
|
||||
});
|
||||
|
||||
EXPECT_TRUE(var->HasLocationDecoration());
|
||||
EXPECT_TRUE(var->HasBuiltinDecoration());
|
||||
EXPECT_TRUE(var->HasConstantIdDecoration());
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, ConstantId) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t,
|
||||
false, nullptr,
|
||||
VariableDecorationList{
|
||||
create<ConstantIdDecoration>(1200, Source{}),
|
||||
});
|
||||
|
||||
EXPECT_EQ(var->constant_id(), 1200u);
|
||||
}
|
||||
|
||||
TEST_F(VariableTest, Decorated_to_str) {
|
||||
type::F32 t;
|
||||
auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t,
|
||||
false, create<IdentifierExpression>("expr"),
|
||||
VariableDecorationList{
|
||||
create<BindingDecoration>(2, Source{}),
|
||||
create<SetDecoration>(1, Source{}),
|
||||
});
|
||||
|
||||
std::ostringstream out;
|
||||
var->to_str(out, 2);
|
||||
EXPECT_EQ(out.str(), R"( Variable{
|
||||
Decorations{
|
||||
BindingDecoration{2}
|
||||
SetDecoration{1}
|
||||
}
|
||||
my_var
|
||||
function
|
||||
__f32
|
||||
{
|
||||
Identifier[not set]{expr}
|
||||
}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
Reference in New Issue
Block a user