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:
Ben Clayton
2020-12-11 13:07:02 +00:00
committed by Commit Bot service account
parent ccc67252ff
commit a80511e021
79 changed files with 4259 additions and 2268 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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;

View File

@@ -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{});

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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