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:
Ben Clayton 2023-02-05 12:36:50 +00:00 committed by Dawn LUCI CQ
parent 8aaa2797c1
commit ad3156551c
31 changed files with 158 additions and 96 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -76,7 +76,7 @@ struct SimplifyPointers::State {
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
CollectSavedArrayIndices(m->structure, cb);
CollectSavedArrayIndices(m->object, cb);
return;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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