tint/ast: Add AccessorExpression
New base class to IndexAccessorExpression and MemberAccessorExpression. Simplfies code that operates on both of these. Change-Id: I02ce2e8180d7c1836f0b4d8e629e707e19e3539e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118403 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
8aaa2797c1
commit
ad3156551c
|
@ -237,6 +237,7 @@ libtint_source_set("libtint_base_src") {
|
|||
|
||||
libtint_source_set("libtint_syntax_tree_src") {
|
||||
sources = [
|
||||
"ast/accessor_expression.h",
|
||||
"ast/alias.h",
|
||||
"ast/array.h",
|
||||
"ast/assignment_statement.h",
|
||||
|
@ -544,6 +545,8 @@ libtint_source_set("libtint_transform_src") {
|
|||
|
||||
libtint_source_set("libtint_ast_src") {
|
||||
sources = [
|
||||
"ast/accessor_expression.cc",
|
||||
"ast/accessor_expression.h",
|
||||
"ast/alias.cc",
|
||||
"ast/alias.h",
|
||||
"ast/array.cc",
|
||||
|
|
|
@ -78,6 +78,8 @@ endif()
|
|||
|
||||
list(APPEND TINT_LIB_SRCS
|
||||
../../include/tint/tint.h
|
||||
ast/accessor_expression.cc
|
||||
ast/accessor_expression.h
|
||||
ast/alias.cc
|
||||
ast/alias.h
|
||||
ast/array.cc
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2023 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/ast/accessor_expression.h"
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::AccessorExpression);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
AccessorExpression::AccessorExpression(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
const Expression* obj)
|
||||
: Base(pid, nid, src), object(obj) {
|
||||
TINT_ASSERT(AST, object);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, object, program_id);
|
||||
}
|
||||
|
||||
AccessorExpression::AccessorExpression(AccessorExpression&&) = default;
|
||||
|
||||
AccessorExpression::~AccessorExpression() = default;
|
||||
|
||||
} // namespace tint::ast
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2023 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_TINT_AST_ACCESSOR_EXPRESSION_H_
|
||||
#define SRC_TINT_AST_ACCESSOR_EXPRESSION_H_
|
||||
|
||||
#include "src/tint/ast/expression.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// Base class for IndexAccessorExpression and MemberAccessorExpression
|
||||
class AccessorExpression : public Castable<AccessorExpression, Expression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param nid the unique node identifier
|
||||
/// @param source the member accessor expression source
|
||||
/// @param object the object
|
||||
AccessorExpression(ProgramID pid, NodeID nid, const Source& source, const Expression* object);
|
||||
/// Move constructor
|
||||
AccessorExpression(AccessorExpression&&);
|
||||
~AccessorExpression() override;
|
||||
|
||||
/// The object being accessed
|
||||
const Expression* const object;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
#endif // SRC_TINT_AST_ACCESSOR_EXPRESSION_H_
|
|
@ -25,9 +25,7 @@ IndexAccessorExpression::IndexAccessorExpression(ProgramID pid,
|
|||
const Source& src,
|
||||
const Expression* obj,
|
||||
const Expression* idx)
|
||||
: Base(pid, nid, src), object(obj), index(idx) {
|
||||
TINT_ASSERT(AST, object);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, object, program_id);
|
||||
: Base(pid, nid, src, obj), index(idx) {
|
||||
TINT_ASSERT(AST, idx);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, idx, program_id);
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#ifndef SRC_TINT_AST_INDEX_ACCESSOR_EXPRESSION_H_
|
||||
#define SRC_TINT_AST_INDEX_ACCESSOR_EXPRESSION_H_
|
||||
|
||||
#include "src/tint/ast/expression.h"
|
||||
#include "src/tint/ast/accessor_expression.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// An index accessor expression
|
||||
class IndexAccessorExpression final : public Castable<IndexAccessorExpression, Expression> {
|
||||
class IndexAccessorExpression final : public Castable<IndexAccessorExpression, AccessorExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
|
@ -43,9 +43,6 @@ class IndexAccessorExpression final : public Castable<IndexAccessorExpression, E
|
|||
/// @return the newly cloned node
|
||||
const IndexAccessorExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the array, vector or matrix
|
||||
const Expression* const object;
|
||||
|
||||
/// the index expression
|
||||
const Expression* const index;
|
||||
};
|
||||
|
|
|
@ -23,11 +23,9 @@ namespace tint::ast {
|
|||
MemberAccessorExpression::MemberAccessorExpression(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
const Expression* str,
|
||||
const Expression* obj,
|
||||
const Identifier* mem)
|
||||
: Base(pid, nid, src), structure(str), member(mem) {
|
||||
TINT_ASSERT(AST, structure);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, structure, program_id);
|
||||
: Base(pid, nid, src, obj), member(mem) {
|
||||
TINT_ASSERT(AST, member);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, member, program_id);
|
||||
|
||||
|
@ -44,9 +42,9 @@ MemberAccessorExpression::~MemberAccessorExpression() = default;
|
|||
const MemberAccessorExpression* MemberAccessorExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* str = ctx->Clone(structure);
|
||||
auto* obj = ctx->Clone(object);
|
||||
auto* mem = ctx->Clone(member);
|
||||
return ctx->dst->create<MemberAccessorExpression>(src, str, mem);
|
||||
return ctx->dst->create<MemberAccessorExpression>(src, obj, mem);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -15,23 +15,25 @@
|
|||
#ifndef SRC_TINT_AST_MEMBER_ACCESSOR_EXPRESSION_H_
|
||||
#define SRC_TINT_AST_MEMBER_ACCESSOR_EXPRESSION_H_
|
||||
|
||||
#include "src/tint/ast/accessor_expression.h"
|
||||
#include "src/tint/ast/identifier_expression.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// A member accessor expression
|
||||
class MemberAccessorExpression final : public Castable<MemberAccessorExpression, Expression> {
|
||||
class MemberAccessorExpression final
|
||||
: public Castable<MemberAccessorExpression, AccessorExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param nid the unique node identifier
|
||||
/// @param source the member accessor expression source
|
||||
/// @param structure the structure
|
||||
/// @param object the object
|
||||
/// @param member the member
|
||||
MemberAccessorExpression(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& source,
|
||||
const Expression* structure,
|
||||
const Expression* object,
|
||||
const Identifier* member);
|
||||
/// Move constructor
|
||||
MemberAccessorExpression(MemberAccessorExpression&&);
|
||||
|
@ -43,9 +45,6 @@ class MemberAccessorExpression final : public Castable<MemberAccessorExpression,
|
|||
/// @return the newly cloned node
|
||||
const MemberAccessorExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The structure
|
||||
const Expression* const structure;
|
||||
|
||||
/// The member expression
|
||||
const Identifier* const member;
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ TEST_F(MemberAccessorExpressionTest, Creation) {
|
|||
auto* mem = Ident("member");
|
||||
|
||||
auto* stmt = create<MemberAccessorExpression>(str, mem);
|
||||
EXPECT_EQ(stmt->structure, str);
|
||||
EXPECT_EQ(stmt->object, str);
|
||||
EXPECT_EQ(stmt->member, mem);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ bool TraverseExpressions(const ast::Expression* root, diag::List& diags, CALLBAC
|
|||
return true;
|
||||
},
|
||||
[&](const MemberAccessorExpression* member) {
|
||||
push_single(member->structure, p.depth + 1);
|
||||
push_single(member->object, p.depth + 1);
|
||||
return true;
|
||||
},
|
||||
[&](const UnaryOpExpression* unary) {
|
||||
|
|
|
@ -73,8 +73,8 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
|||
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("d"));
|
||||
|
||||
ASSERT_TRUE(mem->structure->Is<ast::IndexAccessorExpression>());
|
||||
auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
|
||||
ASSERT_TRUE(mem->object->Is<ast::IndexAccessorExpression>());
|
||||
auto* idx = mem->object->As<ast::IndexAccessorExpression>();
|
||||
|
||||
ASSERT_NE(idx->index, nullptr);
|
||||
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
|
||||
|
@ -84,11 +84,11 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
|||
mem = idx->object->As<ast::MemberAccessorExpression>();
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("c"));
|
||||
|
||||
ASSERT_TRUE(mem->structure->Is<ast::MemberAccessorExpression>());
|
||||
ASSERT_TRUE(mem->object->Is<ast::MemberAccessorExpression>());
|
||||
|
||||
mem = mem->structure->As<ast::MemberAccessorExpression>();
|
||||
ASSERT_TRUE(mem->structure->Is<ast::IdentifierExpression>());
|
||||
auto* ident_expr = mem->structure->As<ast::IdentifierExpression>();
|
||||
mem = mem->object->As<ast::MemberAccessorExpression>();
|
||||
ASSERT_TRUE(mem->object->Is<ast::IdentifierExpression>());
|
||||
auto* ident_expr = mem->object->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
|
|
@ -92,8 +92,8 @@ TEST_F(ParserImplTest, IncrementDecrementStmt_ToMember) {
|
|||
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("d"));
|
||||
|
||||
ASSERT_TRUE(mem->structure->Is<ast::IndexAccessorExpression>());
|
||||
auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
|
||||
ASSERT_TRUE(mem->object->Is<ast::IndexAccessorExpression>());
|
||||
auto* idx = mem->object->As<ast::IndexAccessorExpression>();
|
||||
|
||||
ASSERT_NE(idx->index, nullptr);
|
||||
ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
|
||||
|
@ -103,11 +103,11 @@ TEST_F(ParserImplTest, IncrementDecrementStmt_ToMember) {
|
|||
mem = idx->object->As<ast::MemberAccessorExpression>();
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("c"));
|
||||
|
||||
ASSERT_TRUE(mem->structure->Is<ast::MemberAccessorExpression>());
|
||||
mem = mem->structure->As<ast::MemberAccessorExpression>();
|
||||
ASSERT_TRUE(mem->object->Is<ast::MemberAccessorExpression>());
|
||||
mem = mem->object->As<ast::MemberAccessorExpression>();
|
||||
|
||||
ASSERT_TRUE(mem->structure->Is<ast::IdentifierExpression>());
|
||||
auto* ident_expr = mem->structure->As<ast::IdentifierExpression>();
|
||||
ASSERT_TRUE(mem->object->Is<ast::IdentifierExpression>());
|
||||
auto* ident_expr = mem->object->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
|
||||
EXPECT_EQ(mem->member->symbol, p->builder().Symbols().Get("b"));
|
||||
}
|
||||
|
|
|
@ -143,9 +143,9 @@ TEST_F(ParserImplTest, LHSExpression_PostfixExpression) {
|
|||
ASSERT_TRUE(u->expr->Is<ast::MemberAccessorExpression>());
|
||||
|
||||
auto* access = u->expr->As<ast::MemberAccessorExpression>();
|
||||
ASSERT_TRUE(access->structure->Is<ast::IdentifierExpression>());
|
||||
ASSERT_TRUE(access->object->Is<ast::IdentifierExpression>());
|
||||
|
||||
auto* struct_ident = access->structure->As<ast::IdentifierExpression>();
|
||||
auto* struct_ident = access->object->As<ast::IdentifierExpression>();
|
||||
EXPECT_EQ(struct_ident->identifier->symbol, p->builder().Symbols().Get("a"));
|
||||
EXPECT_EQ(access->member->symbol, p->builder().Symbols().Get("foo"));
|
||||
}
|
||||
|
|
|
@ -163,8 +163,8 @@ TEST_F(ParserImplTest, SingularExpression_MemberAccessor) {
|
|||
ASSERT_TRUE(e->Is<ast::MemberAccessorExpression>());
|
||||
|
||||
auto* m = e->As<ast::MemberAccessorExpression>();
|
||||
ASSERT_TRUE(m->structure->Is<ast::IdentifierExpression>());
|
||||
EXPECT_EQ(m->structure->As<ast::IdentifierExpression>()->identifier->symbol,
|
||||
ASSERT_TRUE(m->object->Is<ast::IdentifierExpression>());
|
||||
EXPECT_EQ(m->object->As<ast::IdentifierExpression>()->identifier->symbol,
|
||||
p->builder().Symbols().Get("a"));
|
||||
|
||||
EXPECT_EQ(m->member->symbol, p->builder().Symbols().Get("b"));
|
||||
|
|
|
@ -2777,9 +2777,9 @@ sem::ValueExpression* Resolver::Identifier(const ast::IdentifierExpression* expr
|
|||
}
|
||||
|
||||
sem::ValueExpression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* expr) {
|
||||
auto* structure = sem_.TypeOf(expr->structure);
|
||||
auto* structure = sem_.TypeOf(expr->object);
|
||||
auto* storage_ty = structure->UnwrapRef();
|
||||
auto* object = sem_.Get(expr->structure);
|
||||
auto* object = sem_.Get(expr->object);
|
||||
auto* root_ident = object->RootIdentifier();
|
||||
|
||||
const type::Type* ty = nullptr;
|
||||
|
@ -3008,7 +3008,7 @@ sem::ValueExpression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
auto* array = unary->expr->As<ast::IndexAccessorExpression>();
|
||||
auto* member = unary->expr->As<ast::MemberAccessorExpression>();
|
||||
if ((array && sem_.TypeOf(array->object)->UnwrapRef()->Is<type::Vector>()) ||
|
||||
(member && sem_.TypeOf(member->structure)->UnwrapRef()->Is<type::Vector>())) {
|
||||
(member && sem_.TypeOf(member->object)->UnwrapRef()->Is<type::Vector>())) {
|
||||
AddError("cannot take the address of a vector component", unary->expr->source);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -1253,7 +1253,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
|
|||
auto* sma = Sem().Get(mem)->UnwrapLoad()->As<sem::StructMemberAccess>();
|
||||
ASSERT_NE(sma, nullptr);
|
||||
EXPECT_TRUE(sma->Member()->Type()->Is<type::F32>());
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->structure);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->object);
|
||||
EXPECT_EQ(sma->Member()->Index(), 1u);
|
||||
EXPECT_EQ(sma->Member()->Declaration()->symbol, Symbols().Get("second_member"));
|
||||
}
|
||||
|
@ -1273,7 +1273,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
|
|||
EXPECT_TRUE(TypeOf(mem)->Is<type::F32>());
|
||||
auto* sma = Sem().Get(mem)->UnwrapLoad()->As<sem::StructMemberAccess>();
|
||||
ASSERT_NE(sma, nullptr);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->structure);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->object);
|
||||
EXPECT_TRUE(sma->Member()->Type()->Is<type::F32>());
|
||||
EXPECT_EQ(sma->Member()->Index(), 1u);
|
||||
}
|
||||
|
@ -1292,7 +1292,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
|
|||
EXPECT_EQ(TypeOf(mem)->As<type::Vector>()->Width(), 4u);
|
||||
auto* sma = Sem().Get(mem)->As<sem::Swizzle>();
|
||||
ASSERT_NE(sma, nullptr);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->structure);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->object);
|
||||
EXPECT_THAT(sma->Indices(), ElementsAre(0, 2, 1, 3));
|
||||
}
|
||||
|
||||
|
@ -1308,7 +1308,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) {
|
|||
ASSERT_TRUE(TypeOf(mem)->Is<type::F32>());
|
||||
auto* sma = Sem().Get(mem)->UnwrapLoad()->As<sem::Swizzle>();
|
||||
ASSERT_NE(sma, nullptr);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->structure);
|
||||
EXPECT_EQ(sma->Object()->Declaration(), mem->object);
|
||||
EXPECT_THAT(sma->Indices(), ElementsAre(2));
|
||||
}
|
||||
|
||||
|
|
|
@ -1092,8 +1092,7 @@ class UniformityGraph {
|
|||
auto* init = sem_.Get(decl->variable->initializer);
|
||||
if (auto* unary_init = init->Declaration()->As<ast::UnaryOpExpression>()) {
|
||||
auto* e = UnwrapIndirectAndAddressOfChain(unary_init);
|
||||
if (e->IsAnyOf<ast::IndexAccessorExpression,
|
||||
ast::MemberAccessorExpression>()) {
|
||||
if (e->Is<ast::AccessorExpression>()) {
|
||||
current_function_->partial_ptrs.Add(sem_var);
|
||||
}
|
||||
}
|
||||
|
@ -1311,7 +1310,7 @@ class UniformityGraph {
|
|||
[&](const ast::LiteralExpression*) { return std::make_pair(cf, cf); },
|
||||
|
||||
[&](const ast::MemberAccessorExpression* m) {
|
||||
return ProcessExpression(cf, m->structure, load_rule);
|
||||
return ProcessExpression(cf, m->object, load_rule);
|
||||
},
|
||||
|
||||
[&](const ast::UnaryOpExpression* u) {
|
||||
|
@ -1341,9 +1340,7 @@ class UniformityGraph {
|
|||
return true;
|
||||
}
|
||||
} else {
|
||||
TINT_ASSERT(
|
||||
Resolver,
|
||||
(e->IsAnyOf<ast::IndexAccessorExpression, ast::MemberAccessorExpression>()));
|
||||
TINT_ASSERT(Resolver, e->Is<ast::IndexAccessorExpression>());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1394,7 +1391,7 @@ class UniformityGraph {
|
|||
},
|
||||
|
||||
[&](const ast::MemberAccessorExpression* m) {
|
||||
return ProcessLValueExpression(cf, m->structure, /*is_partial_reference*/ true);
|
||||
return ProcessLValueExpression(cf, m->object, /*is_partial_reference*/ true);
|
||||
},
|
||||
|
||||
[&](const ast::UnaryOpExpression* u) {
|
||||
|
|
|
@ -226,7 +226,7 @@ struct ArrayLengthFromUniform::State {
|
|||
}
|
||||
auto* storage_buffer_expr = param->expr;
|
||||
if (auto* accessor = param->expr->As<ast::MemberAccessorExpression>()) {
|
||||
storage_buffer_expr = accessor->structure;
|
||||
storage_buffer_expr = accessor->object;
|
||||
}
|
||||
auto* storage_buffer_sem = sem.Get<sem::VariableUser>(storage_buffer_expr);
|
||||
if (TINT_UNLIKELY(!storage_buffer_sem)) {
|
||||
|
|
|
@ -158,7 +158,7 @@ Transform::ApplyResult CalculateArrayLength::Apply(const Program* src,
|
|||
}
|
||||
auto* storage_buffer_expr = address_of->expr;
|
||||
if (auto* accessor = storage_buffer_expr->As<ast::MemberAccessorExpression>()) {
|
||||
storage_buffer_expr = accessor->structure;
|
||||
storage_buffer_expr = accessor->object;
|
||||
}
|
||||
auto* storage_buffer_sem = sem.Get<sem::VariableUser>(storage_buffer_expr);
|
||||
if (TINT_UNLIKELY(!storage_buffer_sem)) {
|
||||
|
|
|
@ -902,7 +902,7 @@ Transform::ApplyResult DecomposeMemoryAccess::Apply(const Program* src,
|
|||
auto* accessor_sem = sem.Get(accessor)->UnwrapLoad();
|
||||
if (auto* swizzle = accessor_sem->As<sem::Swizzle>()) {
|
||||
if (swizzle->Indices().Length() == 1) {
|
||||
if (auto access = state.TakeAccess(accessor->structure)) {
|
||||
if (auto access = state.TakeAccess(accessor->object)) {
|
||||
auto* vec_ty = access.type->As<type::Vector>();
|
||||
auto* offset = state.Mul(vec_ty->type()->Size(), swizzle->Indices()[0u]);
|
||||
state.AddAccess(accessor, {
|
||||
|
@ -913,7 +913,7 @@ Transform::ApplyResult DecomposeMemoryAccess::Apply(const Program* src,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (auto access = state.TakeAccess(accessor->structure)) {
|
||||
if (auto access = state.TakeAccess(accessor->object)) {
|
||||
auto* str_ty = access.type->As<sem::Struct>();
|
||||
auto* member = str_ty->FindMember(accessor->member->symbol);
|
||||
auto offset = member->Offset();
|
||||
|
|
|
@ -96,7 +96,7 @@ struct ExpandCompoundAssignment::State {
|
|||
auto* index_accessor = lhs->As<ast::IndexAccessorExpression>();
|
||||
auto* member_accessor = lhs->As<ast::MemberAccessorExpression>();
|
||||
if (lhs->Is<ast::IdentifierExpression>() ||
|
||||
(member_accessor && member_accessor->structure->Is<ast::IdentifierExpression>())) {
|
||||
(member_accessor && member_accessor->object->Is<ast::IdentifierExpression>())) {
|
||||
// This is the simple case with no side effects, so we can just use the
|
||||
// original LHS expression directly.
|
||||
// Before:
|
||||
|
@ -116,7 +116,7 @@ struct ExpandCompoundAssignment::State {
|
|||
auto lhs_ptr = hoist_pointer_to(index_accessor->object);
|
||||
auto index = hoist_expr_to_let(index_accessor->index);
|
||||
new_lhs = [&, lhs_ptr, index]() { return b.IndexAccessor(b.Deref(lhs_ptr), index); };
|
||||
} else if (member_accessor && is_vec(member_accessor->structure)) {
|
||||
} else if (member_accessor && is_vec(member_accessor->object)) {
|
||||
// This is the case for vector component via a member accessor. We just
|
||||
// need to capture a pointer to the vector.
|
||||
// Before:
|
||||
|
@ -124,7 +124,7 @@ struct ExpandCompoundAssignment::State {
|
|||
// After:
|
||||
// let vec_ptr = &a[idx()];
|
||||
// (*vec_ptr).y = (*vec_ptr).y + rhs;
|
||||
auto lhs_ptr = hoist_pointer_to(member_accessor->structure);
|
||||
auto lhs_ptr = hoist_pointer_to(member_accessor->object);
|
||||
new_lhs = [&, lhs_ptr]() {
|
||||
return b.MemberAccessor(b.Deref(lhs_ptr), ctx.Clone(member_accessor->member));
|
||||
};
|
||||
|
|
|
@ -172,7 +172,7 @@ Transform::ApplyResult NumWorkgroupsFromUniform::Apply(const Program* src,
|
|||
if (!accessor) {
|
||||
continue;
|
||||
}
|
||||
auto* ident = accessor->structure->As<ast::IdentifierExpression>();
|
||||
auto* ident = accessor->object->As<ast::IdentifierExpression>();
|
||||
if (!ident) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ class DecomposeSideEffects::CollectHoistsState : public StateBase {
|
|||
return false;
|
||||
},
|
||||
[&](const ast::MemberAccessorExpression* e) {
|
||||
if (HasSideEffects(e->structure)) {
|
||||
if (HasSideEffects(e->object)) {
|
||||
return true;
|
||||
}
|
||||
no_side_effects.insert(e);
|
||||
|
@ -323,7 +323,7 @@ class DecomposeSideEffects::CollectHoistsState : public StateBase {
|
|||
[&](const ast::IndexAccessorExpression* e) {
|
||||
return accessor_process(e->object, e->index);
|
||||
},
|
||||
[&](const ast::MemberAccessorExpression* e) { return accessor_process(e->structure); },
|
||||
[&](const ast::MemberAccessorExpression* e) { return accessor_process(e->object); },
|
||||
[&](const ast::LiteralExpression*) {
|
||||
// Leaf
|
||||
return false;
|
||||
|
@ -519,7 +519,7 @@ class DecomposeSideEffects::DecomposeState : public StateBase {
|
|||
return clone_maybe_hoisted(call);
|
||||
},
|
||||
[&](const ast::MemberAccessorExpression* member) {
|
||||
ctx.Replace(member->structure, decompose(member->structure));
|
||||
ctx.Replace(member->object, decompose(member->object));
|
||||
return clone_maybe_hoisted(member);
|
||||
},
|
||||
[&](const ast::UnaryOpExpression* unary) {
|
||||
|
|
|
@ -1286,7 +1286,7 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
|
|||
auto* sem = src->Sem().Get(accessor)->UnwrapLoad();
|
||||
if (sem->Is<sem::Swizzle>()) {
|
||||
preserved_identifiers.Add(accessor->member);
|
||||
} else if (auto* str_expr = src->Sem().Get(accessor->structure)) {
|
||||
} else if (auto* str_expr = src->Sem().Get(accessor->object)) {
|
||||
if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
|
||||
if (ty->Declaration() == nullptr) { // Builtin structure
|
||||
preserved_identifiers.Add(accessor->member);
|
||||
|
|
|
@ -76,7 +76,7 @@ struct SimplifyPointers::State {
|
|||
}
|
||||
|
||||
if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
|
||||
CollectSavedArrayIndices(m->structure, cb);
|
||||
CollectSavedArrayIndices(m->object, cb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2720,7 +2720,7 @@ bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
|
|||
|
||||
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
|
||||
const ast::MemberAccessorExpression* expr) {
|
||||
if (!EmitExpression(out, expr->structure)) {
|
||||
if (!EmitExpression(out, expr->object)) {
|
||||
return false;
|
||||
}
|
||||
out << ".";
|
||||
|
|
|
@ -3745,7 +3745,7 @@ bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
|
|||
|
||||
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
|
||||
const ast::MemberAccessorExpression* expr) {
|
||||
if (!EmitExpression(out, expr->structure)) {
|
||||
if (!EmitExpression(out, expr->object)) {
|
||||
return false;
|
||||
}
|
||||
out << ".";
|
||||
|
|
|
@ -370,8 +370,8 @@ bool GeneratorImpl::EmitTypeDecl(const type::Type* ty) {
|
|||
|
||||
bool GeneratorImpl::EmitIndexAccessor(std::ostream& out, const ast::IndexAccessorExpression* expr) {
|
||||
bool paren_lhs =
|
||||
!expr->object->IsAnyOf<ast::IndexAccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression, ast::MemberAccessorExpression>();
|
||||
!expr->object
|
||||
->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>();
|
||||
|
||||
if (paren_lhs) {
|
||||
out << "(";
|
||||
|
@ -1009,9 +1009,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
|
|||
// expression includes an operator with lower precedence than the member
|
||||
// accessor used for the function calls.
|
||||
auto texture_expr = [&]() {
|
||||
bool paren_lhs =
|
||||
!texture->IsAnyOf<ast::IndexAccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression, ast::MemberAccessorExpression>();
|
||||
bool paren_lhs = !texture->IsAnyOf<ast::AccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression>();
|
||||
if (paren_lhs) {
|
||||
out << "(";
|
||||
}
|
||||
|
@ -2331,13 +2330,12 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
|
|||
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
|
||||
const ast::MemberAccessorExpression* expr) {
|
||||
auto write_lhs = [&] {
|
||||
bool paren_lhs =
|
||||
!expr->structure->IsAnyOf<ast::IndexAccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression, ast::MemberAccessorExpression>();
|
||||
bool paren_lhs = !expr->object->IsAnyOf<ast::AccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression>();
|
||||
if (paren_lhs) {
|
||||
out << "(";
|
||||
}
|
||||
if (!EmitExpression(out, expr->structure)) {
|
||||
if (!EmitExpression(out, expr->object)) {
|
||||
return false;
|
||||
}
|
||||
if (paren_lhs) {
|
||||
|
|
|
@ -571,13 +571,12 @@ uint32_t Builder::GenerateExpression(const sem::ValueExpression* expr) {
|
|||
}
|
||||
return Switch(
|
||||
expr->Declaration(), //
|
||||
[&](const ast::IndexAccessorExpression* a) { return GenerateAccessorExpression(a); },
|
||||
[&](const ast::AccessorExpression* a) { return GenerateAccessorExpression(a); },
|
||||
[&](const ast::BinaryExpression* b) { return GenerateBinaryExpression(b); },
|
||||
[&](const ast::BitcastExpression* b) { return GenerateBitcastExpression(b); },
|
||||
[&](const ast::CallExpression* c) { return GenerateCallExpression(c); },
|
||||
[&](const ast::IdentifierExpression* i) { return GenerateIdentifierExpression(i); },
|
||||
[&](const ast::LiteralExpression* l) { return GenerateLiteralIfNeeded(l); },
|
||||
[&](const ast::MemberAccessorExpression* m) { return GenerateAccessorExpression(m); },
|
||||
[&](const ast::UnaryOpExpression* u) { return GenerateUnaryOpExpression(u); },
|
||||
[&](Default) {
|
||||
error_ = "unknown expression type: " + std::string(expr->TypeInfo().name);
|
||||
|
@ -1070,13 +1069,7 @@ bool Builder::GenerateMemberAccessor(const ast::MemberAccessorExpression* expr,
|
|||
});
|
||||
}
|
||||
|
||||
uint32_t Builder::GenerateAccessorExpression(const ast::Expression* expr) {
|
||||
if (TINT_UNLIKELY(
|
||||
(!expr->IsAnyOf<ast::IndexAccessorExpression, ast::MemberAccessorExpression>()))) {
|
||||
TINT_ICE(Writer, builder_.Diagnostics()) << "expression is not an accessor";
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Builder::GenerateAccessorExpression(const ast::AccessorExpression* expr) {
|
||||
// Gather a list of all the member and index accessors that are in this chain.
|
||||
// The list is built in reverse order as that's the order we need to access
|
||||
// the chain.
|
||||
|
@ -1088,7 +1081,7 @@ uint32_t Builder::GenerateAccessorExpression(const ast::Expression* expr) {
|
|||
source = array->object;
|
||||
} else if (auto* member = source->As<ast::MemberAccessorExpression>()) {
|
||||
accessors.insert(accessors.begin(), source);
|
||||
source = member->structure;
|
||||
source = member->object;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -2380,13 +2373,13 @@ uint32_t Builder::GenerateBuiltinCall(const sem::Call* call, const sem::Builtin*
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto struct_id = GenerateExpression(accessor->structure);
|
||||
auto struct_id = GenerateExpression(accessor->object);
|
||||
if (struct_id == 0) {
|
||||
return 0;
|
||||
}
|
||||
params.push_back(Operand(struct_id));
|
||||
|
||||
auto* type = TypeOf(accessor->structure)->UnwrapRef();
|
||||
auto* type = TypeOf(accessor->object)->UnwrapRef();
|
||||
if (!type->Is<sem::Struct>()) {
|
||||
error_ = "invalid type (" + type->FriendlyName(builder_.Symbols()) +
|
||||
") for runtime array length";
|
||||
|
|
|
@ -308,9 +308,9 @@ class Builder {
|
|||
/// For more information on accessors see the "Pointer evaluation" section of
|
||||
/// the WGSL specification.
|
||||
///
|
||||
/// @param expr the expresssion to generate
|
||||
/// @param expr the expression to generate
|
||||
/// @returns the id of the expression or 0 on failure
|
||||
uint32_t GenerateAccessorExpression(const ast::Expression* expr);
|
||||
uint32_t GenerateAccessorExpression(const ast::AccessorExpression* expr);
|
||||
/// Generates an index accessor
|
||||
/// @param expr the accessor to generate
|
||||
/// @param info the current accessor information
|
||||
|
@ -322,7 +322,7 @@ class Builder {
|
|||
/// @returns true if the accessor was generated successfully
|
||||
bool GenerateMemberAccessor(const ast::MemberAccessorExpression* expr, AccessorInfo* info);
|
||||
/// Generates an identifier expression
|
||||
/// @param expr the expresssion to generate
|
||||
/// @param expr the expression to generate
|
||||
/// @returns the id of the expression or 0 on failure
|
||||
uint32_t GenerateIdentifierExpression(const ast::IdentifierExpression* expr);
|
||||
/// Generates a unary op expression
|
||||
|
|
|
@ -181,8 +181,8 @@ bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* exp
|
|||
|
||||
bool GeneratorImpl::EmitIndexAccessor(std::ostream& out, const ast::IndexAccessorExpression* expr) {
|
||||
bool paren_lhs =
|
||||
!expr->object->IsAnyOf<ast::IndexAccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression, ast::MemberAccessorExpression>();
|
||||
!expr->object
|
||||
->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>();
|
||||
if (paren_lhs) {
|
||||
out << "(";
|
||||
}
|
||||
|
@ -205,12 +205,12 @@ bool GeneratorImpl::EmitIndexAccessor(std::ostream& out, const ast::IndexAccesso
|
|||
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
|
||||
const ast::MemberAccessorExpression* expr) {
|
||||
bool paren_lhs =
|
||||
!expr->structure->IsAnyOf<ast::IndexAccessorExpression, ast::CallExpression,
|
||||
ast::IdentifierExpression, ast::MemberAccessorExpression>();
|
||||
!expr->object
|
||||
->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>();
|
||||
if (paren_lhs) {
|
||||
out << "(";
|
||||
}
|
||||
if (!EmitExpression(out, expr->structure)) {
|
||||
if (!EmitExpression(out, expr->object)) {
|
||||
return false;
|
||||
}
|
||||
if (paren_lhs) {
|
||||
|
|
Loading…
Reference in New Issue