mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
tint/writer/msl: Generate an array<T,N> helper
And remove the WrapArraysInStructs transform. Wrapping arrays in structures becomes troublesome for `const` arrays, as currently WGSL does not allow `const` structures. MSL 2.0+ has a builtin array<> helper, but we're targetting MSL 1.2, so we have to emit our own. Fortunately, it can be done with a few lines of templated code. This produces significantly cleaner output. Change-Id: Ifc92ef21e09befa252a07c856c4b5afdc51cc2e4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94540 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
3c054304a8
commit
f47887d207
@@ -1,158 +0,0 @@
|
||||
// Copyright 2021 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/transform/wrap_arrays_in_structs.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/sem/array.h"
|
||||
#include "src/tint/sem/call.h"
|
||||
#include "src/tint/sem/expression.h"
|
||||
#include "src/tint/sem/type_constructor.h"
|
||||
#include "src/tint/utils/map.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::WrapArraysInStructs);
|
||||
|
||||
namespace tint::transform {
|
||||
|
||||
WrapArraysInStructs::WrappedArrayInfo::WrappedArrayInfo() = default;
|
||||
WrapArraysInStructs::WrappedArrayInfo::WrappedArrayInfo(const WrappedArrayInfo&) = default;
|
||||
WrapArraysInStructs::WrappedArrayInfo::~WrappedArrayInfo() = default;
|
||||
|
||||
WrapArraysInStructs::WrapArraysInStructs() = default;
|
||||
|
||||
WrapArraysInStructs::~WrapArraysInStructs() = default;
|
||||
|
||||
bool WrapArraysInStructs::ShouldRun(const Program* program, const DataMap&) const {
|
||||
for (auto* node : program->ASTNodes().Objects()) {
|
||||
if (program->Sem().Get<sem::Array>(node->As<ast::Type>())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WrapArraysInStructs::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
|
||||
auto& sem = ctx.src->Sem();
|
||||
|
||||
std::unordered_map<const sem::Array*, WrappedArrayInfo> wrapped_arrays;
|
||||
auto wrapper = [&](const sem::Array* array) { return WrapArray(ctx, wrapped_arrays, array); };
|
||||
auto wrapper_typename = [&](const sem::Array* arr) -> ast::TypeName* {
|
||||
auto info = wrapper(arr);
|
||||
return info ? ctx.dst->create<ast::TypeName>(info.wrapper_name) : nullptr;
|
||||
};
|
||||
|
||||
// Replace all array types with their corresponding wrapper
|
||||
ctx.ReplaceAll([&](const ast::Type* ast_type) -> const ast::Type* {
|
||||
auto* type = ctx.src->TypeOf(ast_type);
|
||||
if (auto* array = type->UnwrapRef()->As<sem::Array>()) {
|
||||
return wrapper_typename(array);
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
// Fix up index accessors so `a[1]` becomes `a.arr[1]`
|
||||
ctx.ReplaceAll(
|
||||
[&](const ast::IndexAccessorExpression* accessor) -> const ast::IndexAccessorExpression* {
|
||||
if (auto* array =
|
||||
::tint::As<sem::Array>(sem.Get(accessor->object)->Type()->UnwrapRef())) {
|
||||
if (wrapper(array)) {
|
||||
// Array is wrapped in a structure. Emit a member accessor to get
|
||||
// to the actual array.
|
||||
auto* arr = ctx.Clone(accessor->object);
|
||||
auto* idx = ctx.Clone(accessor->index);
|
||||
auto* unwrapped = ctx.dst->MemberAccessor(arr, "arr");
|
||||
return ctx.dst->IndexAccessor(accessor->source, unwrapped, idx);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
// Fix up array constructors so `A(1,2)` becomes `tint_array_wrapper(A(1,2))`
|
||||
ctx.ReplaceAll([&](const ast::CallExpression* expr) -> const ast::Expression* {
|
||||
if (auto* call = sem.Get(expr)->UnwrapMaterialize()->As<sem::Call>()) {
|
||||
if (auto* ctor = call->Target()->As<sem::TypeConstructor>()) {
|
||||
if (auto* array = ctor->ReturnType()->As<sem::Array>()) {
|
||||
if (auto w = wrapper(array)) {
|
||||
// Wrap the array type constructor with another constructor for
|
||||
// the wrapper
|
||||
auto* wrapped_array_ty = ctx.dst->ty.type_name(w.wrapper_name);
|
||||
auto* array_ty = w.array_type(ctx);
|
||||
auto args = utils::Transform(call->Arguments(),
|
||||
[&](const tint::sem::Expression* s) {
|
||||
return ctx.Clone(s->Declaration());
|
||||
});
|
||||
auto* arr_ctor = ctx.dst->Construct(array_ty, args);
|
||||
return ctx.dst->Construct(wrapped_array_ty, arr_ctor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
WrapArraysInStructs::WrappedArrayInfo WrapArraysInStructs::WrapArray(
|
||||
CloneContext& ctx,
|
||||
std::unordered_map<const sem::Array*, WrappedArrayInfo>& wrapped_arrays,
|
||||
const sem::Array* array) const {
|
||||
if (array->IsRuntimeSized()) {
|
||||
return {}; // We don't want to wrap runtime sized arrays
|
||||
}
|
||||
|
||||
return utils::GetOrCreate(wrapped_arrays, array, [&] {
|
||||
WrappedArrayInfo info;
|
||||
|
||||
// Generate a unique name for the array wrapper
|
||||
info.wrapper_name = ctx.dst->Symbols().New("tint_array_wrapper");
|
||||
|
||||
// Examine the element type. Is it also an array?
|
||||
std::function<const ast::Type*(CloneContext&)> el_type;
|
||||
if (auto* el_array = array->ElemType()->As<sem::Array>()) {
|
||||
// Array of array - call WrapArray() on the element type
|
||||
if (auto el = WrapArray(ctx, wrapped_arrays, el_array)) {
|
||||
el_type = [=](CloneContext& c) {
|
||||
return c.dst->create<ast::TypeName>(el.wrapper_name);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// If the element wasn't an array, just create the typical AST type for it
|
||||
if (!el_type) {
|
||||
el_type = [=](CloneContext& c) { return CreateASTTypeFor(c, array->ElemType()); };
|
||||
}
|
||||
|
||||
// Construct the single structure field type
|
||||
info.array_type = [=](CloneContext& c) {
|
||||
ast::AttributeList attrs;
|
||||
if (!array->IsStrideImplicit()) {
|
||||
attrs.emplace_back(c.dst->create<ast::StrideAttribute>(array->Stride()));
|
||||
}
|
||||
return c.dst->ty.array(el_type(c), u32(array->Count()), std::move(attrs));
|
||||
};
|
||||
|
||||
// Structure() will create and append the ast::Struct to the
|
||||
// global declarations of `ctx.dst`. As we haven't finished building the
|
||||
// current module-scope statement or function, this will be placed
|
||||
// immediately before the usage.
|
||||
ctx.dst->Structure(info.wrapper_name, {ctx.dst->Member("arr", info.array_type(ctx))});
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace tint::transform
|
||||
@@ -1,88 +0,0 @@
|
||||
// Copyright 2021 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_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_
|
||||
#define SRC_TINT_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/tint/transform/transform.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
class Type;
|
||||
} // namespace tint::ast
|
||||
|
||||
namespace tint::transform {
|
||||
|
||||
/// WrapArraysInStructs is a transform that replaces all array types with a
|
||||
/// structure holding a single field of that array type.
|
||||
/// Array index expressions and constructors are also adjusted to deal with this
|
||||
/// wrapping.
|
||||
/// This transform helps with backends that cannot directly return arrays or use
|
||||
/// them as parameters.
|
||||
class WrapArraysInStructs : public Castable<WrapArraysInStructs, Transform> {
|
||||
public:
|
||||
/// Constructor
|
||||
WrapArraysInStructs();
|
||||
|
||||
/// Destructor
|
||||
~WrapArraysInStructs() override;
|
||||
|
||||
/// @param program the program to inspect
|
||||
/// @param data optional extra transform-specific input data
|
||||
/// @returns true if this transform should be run for the given program
|
||||
bool ShouldRun(const Program* program, const DataMap& data = {}) const override;
|
||||
|
||||
protected:
|
||||
/// Runs the transform using the CloneContext built for transforming a
|
||||
/// program. Run() is responsible for calling Clone() on the CloneContext.
|
||||
/// @param ctx the CloneContext primed with the input program and
|
||||
/// ProgramBuilder
|
||||
/// @param inputs optional extra transform-specific input data
|
||||
/// @param outputs optional extra transform-specific output data
|
||||
void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override;
|
||||
|
||||
private:
|
||||
struct WrappedArrayInfo {
|
||||
WrappedArrayInfo();
|
||||
WrappedArrayInfo(const WrappedArrayInfo&);
|
||||
~WrappedArrayInfo();
|
||||
|
||||
Symbol wrapper_name;
|
||||
std::function<const ast::Type*(CloneContext&)> array_type;
|
||||
|
||||
operator bool() { return wrapper_name.IsValid(); }
|
||||
};
|
||||
|
||||
/// WrapArray wraps the fixed-size array type in a new structure (if it hasn't
|
||||
/// already been wrapped). WrapArray will recursively wrap arrays-of-arrays.
|
||||
/// The new structure will be added to module-scope type declarations of
|
||||
/// `ctx.dst`.
|
||||
/// @param ctx the CloneContext
|
||||
/// @param wrapped_arrays a map of src array type to the wrapped structure
|
||||
/// name
|
||||
/// @param array the array type
|
||||
/// @return the name of the structure that wraps the array, or an invalid
|
||||
/// Symbol if this array should not be wrapped
|
||||
WrappedArrayInfo WrapArray(
|
||||
CloneContext& ctx,
|
||||
std::unordered_map<const sem::Array*, WrappedArrayInfo>& wrapped_arrays,
|
||||
const sem::Array* array) const;
|
||||
};
|
||||
|
||||
} // namespace tint::transform
|
||||
|
||||
#endif // SRC_TINT_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_
|
||||
@@ -1,422 +0,0 @@
|
||||
// Copyright 2021 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/transform/wrap_arrays_in_structs.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/transform/test_helper.h"
|
||||
|
||||
namespace tint::transform {
|
||||
namespace {
|
||||
|
||||
using WrapArraysInStructsTest = TransformTest;
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ShouldRunEmptyModule) {
|
||||
auto* src = R"()";
|
||||
|
||||
EXPECT_FALSE(ShouldRun<WrapArraysInStructs>(src));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ShouldRunHasArray) {
|
||||
auto* src = R"(
|
||||
var<private> arr : array<i32, 4>;
|
||||
)";
|
||||
|
||||
EXPECT_TRUE(ShouldRun<WrapArraysInStructs>(src));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, EmptyModule) {
|
||||
auto* src = R"()";
|
||||
auto* expect = src;
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAsGlobal) {
|
||||
auto* src = R"(
|
||||
var<private> arr : array<i32, 4>;
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
var<private> arr : tint_array_wrapper;
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAsFunctionVar) {
|
||||
auto* src = R"(
|
||||
fn f() {
|
||||
var arr : array<i32, 4>;
|
||||
let x = arr[3];
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
fn f() {
|
||||
var arr : tint_array_wrapper;
|
||||
let x = arr.arr[3];
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAsParam) {
|
||||
auto* src = R"(
|
||||
fn f(a : array<i32, 4>) -> i32 {
|
||||
return a[2];
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
fn f(a : tint_array_wrapper) -> i32 {
|
||||
return a.arr[2];
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAsReturn) {
|
||||
auto* src = R"(
|
||||
fn f() -> array<i32, 4> {
|
||||
return array<i32, 4>(1, 2, 3, 4);
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
fn f() -> tint_array_wrapper {
|
||||
return tint_array_wrapper(array<i32, 4u>(1, 2, 3, 4));
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAlias) {
|
||||
auto* src = R"(
|
||||
type Inner = array<i32, 2>;
|
||||
type Array = array<Inner, 2>;
|
||||
|
||||
fn f() {
|
||||
var arr : Array;
|
||||
arr = Array();
|
||||
arr = Array(Inner(1, 2), Inner(3, 4));
|
||||
let vals : Array = Array(Inner(1, 2), Inner(3, 4));
|
||||
arr = vals;
|
||||
let x = arr[3];
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 2u>,
|
||||
}
|
||||
|
||||
type Inner = tint_array_wrapper;
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<tint_array_wrapper, 2u>,
|
||||
}
|
||||
|
||||
type Array = tint_array_wrapper_1;
|
||||
|
||||
fn f() {
|
||||
var arr : tint_array_wrapper_1;
|
||||
arr = tint_array_wrapper_1(array<tint_array_wrapper, 2u>());
|
||||
arr = tint_array_wrapper_1(array<tint_array_wrapper, 2u>(tint_array_wrapper(array<i32, 2u>(1, 2)), tint_array_wrapper(array<i32, 2u>(3, 4))));
|
||||
let vals : tint_array_wrapper_1 = tint_array_wrapper_1(array<tint_array_wrapper, 2u>(tint_array_wrapper(array<i32, 2u>(1, 2)), tint_array_wrapper(array<i32, 2u>(3, 4))));
|
||||
arr = vals;
|
||||
let x = arr.arr[3];
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArrayAlias_OutOfOrder) {
|
||||
auto* src = R"(
|
||||
fn f() {
|
||||
var arr : Array;
|
||||
arr = Array();
|
||||
arr = Array(Inner(1, 2), Inner(3, 4));
|
||||
let vals : Array = Array(Inner(1, 2), Inner(3, 4));
|
||||
arr = vals;
|
||||
let x = arr[3];
|
||||
}
|
||||
|
||||
type Array = array<Inner, 2>;
|
||||
type Inner = array<i32, 2>;
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<i32, 2u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper {
|
||||
arr : array<tint_array_wrapper_1, 2u>,
|
||||
}
|
||||
|
||||
fn f() {
|
||||
var arr : tint_array_wrapper;
|
||||
arr = tint_array_wrapper(array<tint_array_wrapper_1, 2u>());
|
||||
arr = tint_array_wrapper(array<tint_array_wrapper_1, 2u>(tint_array_wrapper_1(array<i32, 2u>(1, 2)), tint_array_wrapper_1(array<i32, 2u>(3, 4))));
|
||||
let vals : tint_array_wrapper = tint_array_wrapper(array<tint_array_wrapper_1, 2u>(tint_array_wrapper_1(array<i32, 2u>(1, 2)), tint_array_wrapper_1(array<i32, 2u>(3, 4))));
|
||||
arr = vals;
|
||||
let x = arr.arr[3];
|
||||
}
|
||||
|
||||
type Array = tint_array_wrapper;
|
||||
|
||||
type Inner = tint_array_wrapper_1;
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArraysInStruct) {
|
||||
auto* src = R"(
|
||||
struct S {
|
||||
a : array<i32, 4>,
|
||||
b : array<i32, 8>,
|
||||
c : array<i32, 4>,
|
||||
};
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<i32, 8u>,
|
||||
}
|
||||
|
||||
struct S {
|
||||
a : tint_array_wrapper,
|
||||
b : tint_array_wrapper_1,
|
||||
c : tint_array_wrapper,
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, ArraysOfArraysInStruct) {
|
||||
auto* src = R"(
|
||||
struct S {
|
||||
a : array<i32, 4>,
|
||||
b : array<array<i32, 4>, 4>,
|
||||
c : array<array<array<i32, 4>, 4>, 4>,
|
||||
};
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<tint_array_wrapper, 4u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper_2 {
|
||||
arr : array<tint_array_wrapper_1, 4u>,
|
||||
}
|
||||
|
||||
struct S {
|
||||
a : tint_array_wrapper,
|
||||
b : tint_array_wrapper_1,
|
||||
c : tint_array_wrapper_2,
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, AccessArraysOfArraysInStruct) {
|
||||
auto* src = R"(
|
||||
struct S {
|
||||
a : array<i32, 4>,
|
||||
b : array<array<i32, 4>, 4>,
|
||||
c : array<array<array<i32, 4>, 4>, 4>,
|
||||
};
|
||||
|
||||
fn f(s : S) -> i32 {
|
||||
return s.a[2] + s.b[1][2] + s.c[3][1][2];
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 4u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<tint_array_wrapper, 4u>,
|
||||
}
|
||||
|
||||
struct tint_array_wrapper_2 {
|
||||
arr : array<tint_array_wrapper_1, 4u>,
|
||||
}
|
||||
|
||||
struct S {
|
||||
a : tint_array_wrapper,
|
||||
b : tint_array_wrapper_1,
|
||||
c : tint_array_wrapper_2,
|
||||
}
|
||||
|
||||
fn f(s : S) -> i32 {
|
||||
return ((s.a.arr[2] + s.b.arr[1].arr[2]) + s.c.arr[3].arr[1].arr[2]);
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, DeclarationOrder) {
|
||||
auto* src = R"(
|
||||
type T0 = i32;
|
||||
|
||||
type T1 = array<i32, 1>;
|
||||
|
||||
type T2 = i32;
|
||||
|
||||
fn f1(a : array<i32, 2>) {
|
||||
}
|
||||
|
||||
type T3 = i32;
|
||||
|
||||
fn f2() {
|
||||
var v : array<i32, 3>;
|
||||
}
|
||||
)";
|
||||
auto* expect = R"(
|
||||
type T0 = i32;
|
||||
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 1u>,
|
||||
}
|
||||
|
||||
type T1 = tint_array_wrapper;
|
||||
|
||||
type T2 = i32;
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<i32, 2u>,
|
||||
}
|
||||
|
||||
fn f1(a : tint_array_wrapper_1) {
|
||||
}
|
||||
|
||||
type T3 = i32;
|
||||
|
||||
struct tint_array_wrapper_2 {
|
||||
arr : array<i32, 3u>,
|
||||
}
|
||||
|
||||
fn f2() {
|
||||
var v : tint_array_wrapper_2;
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(WrapArraysInStructsTest, DeclarationOrder_OutOfOrder) {
|
||||
auto* src = R"(
|
||||
fn f2() {
|
||||
var v : array<i32, 3>;
|
||||
}
|
||||
|
||||
type T3 = i32;
|
||||
|
||||
fn f1(a : array<i32, 2>) {
|
||||
}
|
||||
|
||||
type T2 = i32;
|
||||
|
||||
type T1 = array<i32, 1>;
|
||||
|
||||
type T0 = i32;
|
||||
)";
|
||||
auto* expect = R"(
|
||||
struct tint_array_wrapper {
|
||||
arr : array<i32, 3u>,
|
||||
}
|
||||
|
||||
fn f2() {
|
||||
var v : tint_array_wrapper;
|
||||
}
|
||||
|
||||
type T3 = i32;
|
||||
|
||||
struct tint_array_wrapper_1 {
|
||||
arr : array<i32, 2u>,
|
||||
}
|
||||
|
||||
fn f1(a : tint_array_wrapper_1) {
|
||||
}
|
||||
|
||||
type T2 = i32;
|
||||
|
||||
struct tint_array_wrapper_2 {
|
||||
arr : array<i32, 1u>,
|
||||
}
|
||||
|
||||
type T1 = tint_array_wrapper_2;
|
||||
|
||||
type T0 = i32;
|
||||
)";
|
||||
|
||||
auto got = Run<WrapArraysInStructs>(src);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::transform
|
||||
Reference in New Issue
Block a user