// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/tint/lang/msl/writer/raise/packed_vec3.h"

#include <cstdint>
#include <utility>

#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/type/manager.h"

namespace tint::msl::writer::raise {
namespace {

using namespace tint::core::fluent_types;  // NOLINT

/// Arrays larger than this will be packed/unpacked with a for loop.
/// Arrays up to this size will be packed/unpacked with a sequence of instructions.
static constexpr uint32_t kMaxSeriallyUnpackedArraySize = 8;

/// PIMPL state for the transform.
struct State {
    /// The IR module.
    core::ir::Module& ir;

    /// The IR builder.
    core::ir::Builder b{ir};

    /// The type manager.
    core::type::Manager& ty{ir.Types()};

    /// The symbol table.
    SymbolTable& sym{ir.symbols};

    /// Map from original type to a new type that uses packed vectors.
    Hashmap<const core::type::Type*, const core::type::Type*, 4> rewritten_types{};

    /// Map from a scalar type to the structure that can be used for a packed vector of that type
    /// when inside an array.
    Hashmap<const core::type::Type*, const core::type::Struct*, 4> packed_array_element_types{};

    // A map from an unpacked type to a helper function that will load it from a packed pointer.
    Hashmap<const core::type::Type*, core::ir::Function*, 4> packed_load_helpers{};

    // A map from an unpacked type to a helper function that will store it to a packed pointer.
    Hashmap<const core::type::Type*, core::ir::Function*, 4> packed_store_helpers{};

    /// Process the module.
    void Process() {
        // Find all module-scope variables that contain vec3 types in host-shareable address spaces
        // and update them to use packed vec3 types instead.
        for (auto* inst : *ir.root_block) {
            auto* var = inst->As<core::ir::Var>();
            if (!var) {
                continue;
            }
            auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
            if (!core::IsHostShareable(ptr->AddressSpace())) {
                continue;
            }

            // Rewrite the type, and if anything changed update the variable and its usages.
            auto* packed_store_type = RewriteType(ptr->StoreType());
            if (packed_store_type != ptr->StoreType()) {
                auto* new_ptr = ty.ptr(ptr->AddressSpace(), packed_store_type, ptr->Access());
                var->Result(0)->SetType(new_ptr);
                var->Result(0)->ForEachUseSorted([&](core::ir::Usage use) {  //
                    UpdateUsage(use, ptr->StoreType(), packed_store_type);
                });
            }
        }

        // Find all function parameters that contain vec3 types in host-shareable address spaces and
        // update them to use packed vec3 types instead.
        for (auto func : ir.functions) {
            for (auto* param : func->Params()) {
                auto* ptr = param->Type()->As<core::type::Pointer>();
                if (!ptr || !core::IsHostShareable(ptr->AddressSpace())) {
                    continue;
                }

                // Rewrite the type, and if anything changed update the parameter and its usages.
                auto* packed_store_type = RewriteType(ptr->StoreType());
                if (packed_store_type != ptr->StoreType()) {
                    auto* new_ptr = ty.ptr(ptr->AddressSpace(), packed_store_type, ptr->Access());
                    param->SetType(new_ptr);
                    param->ForEachUseSorted([&](core::ir::Usage use) {  //
                        UpdateUsage(use, ptr->StoreType(), packed_store_type);
                    });
                }
            }
        }
    }

    /// Rewrite a type if necessary, decomposing contained matrices.
    /// @param type the type to rewrite
    /// @returns the new type, or the original type if no changes were needed
    const core::type::Type* RewriteType(const core::type::Type* type) {
        return rewritten_types.GetOrAdd(type, [&] {
            return tint::Switch(
                type,
                [&](const core::type::Array* arr) {  //
                    return RewriteArray(arr);
                },
                [&](const core::type::Matrix* mat) -> const core::type::Type* {
                    if (mat->Rows() == 3) {
                        return ty.array(GetPackedVec3ArrayElementStruct(mat->Type()),
                                        mat->Columns());
                    }
                    return mat;
                },
                [&](const core::type::Pointer* ptr) {
                    auto* store_type = RewriteType(ptr->StoreType());
                    if (store_type != ptr->StoreType()) {
                        return ty.ptr(ptr->AddressSpace(), store_type, ptr->Access());
                    }
                    return ptr;
                },
                [&](const core::type::Struct* str) {  //
                    return RewriteStruct(str);
                },
                [&](const core::type::Vector* vec) {
                    if (vec->Width() == 3) {
                        return ty.packed_vec(vec->Type(), 3);
                    }
                    return vec;
                },
                [&](Default) {
                    // This type cannot contain a vec3, so no changes needed.
                    return type;
                });
        });
    }

    /// @param arr the array type to rewrite if necessary
    /// @returns the new type, or the original type if no changes were needed
    const core::type::Array* RewriteArray(const core::type::Array* arr) {
        // If the element type is a vec3, we need to wrap it in a structure to give it the correct
        // alignment. Otherwise, just recurse and rewrite it.
        const core::type::Type* new_elem_type = nullptr;
        auto* vec = arr->ElemType()->As<core::type::Vector>();
        if (vec && vec->Width() == 3) {
            new_elem_type = GetPackedVec3ArrayElementStruct(vec->Type());
        } else {
            new_elem_type = RewriteType(arr->ElemType());
        }

        if (new_elem_type == arr->ElemType()) {
            // No changes needed.
            return arr;
        }

        if (arr->Count()->Is<core::type::RuntimeArrayCount>()) {
            return ty.runtime_array(new_elem_type);
        } else if (auto count = arr->ConstantCount()) {
            return ty.array(new_elem_type, u32(count.value()));
        }
        TINT_UNREACHABLE();
    }

    /// @param str the struct type to rewrite if necessary
    /// @returns the new type, or the original type if no changes were needed
    const core::type::Struct* RewriteStruct(const core::type::Struct* str) {
        // Recursively rewrite the type of a each member and make a note of whether anything needed
        // to be changed.
        bool has_changed = false;
        Vector<const core::type::StructMember*, 4> new_members;
        new_members.Reserve(str->Members().Length());
        for (auto* member : str->Members()) {
            auto* new_member_type = RewriteType(member->Type());
            if (new_member_type != member->Type()) {
                has_changed = true;
            }

            // Create a struct member with the new type, taking all the layout properties of the
            // original member. No IO attributes should be present on host-shareable structures.
            new_members.Push(ty.Get<core::type::StructMember>(
                member->Name(), new_member_type, static_cast<uint32_t>(new_members.Length()),
                member->Offset(), member->Align(), member->Size(), core::IOAttributes{}));
        }

        // If no members were changed, just return the original struct.
        if (!has_changed) {
            return str;
        }

        // Create a new struct with the rewritten members.
        auto* new_str = ty.Get<core::type::Struct>(sym.New(str->Name().Name() + "_packed_vec3"),
                                                   std::move(new_members), str->Align(),
                                                   str->Size(), str->SizeNoPadding());

        // There are no struct flags that are valid for the MSL backend.
        TINT_ASSERT(str->StructFlags().Empty());

        return new_str;
    }

    /// Get (or create) a structure type that can be used for a packed vector of @p el elements when
    /// inside an array. The structure will have the alignment explicitly set to the required
    /// alignment of the original vec3 type.
    /// @param el the scalar element type
    /// @returns the packed array element type
    const core::type::Struct* GetPackedVec3ArrayElementStruct(const core::type::Type* el) {
        return packed_array_element_types.GetOrAdd(el, [&] {
            auto* packed = ty.packed_vec(el, 3);
            return ty.Struct(
                ir.symbols.New("tint_packed_vec3_" + el->FriendlyName() + "_array_element"),
                Vector{
                    ty.Get<core::type::StructMember>(
                        ir.symbols.New("packed"), packed, /* index */ 0u,
                        /* offset */ 0u, /* align */ 4 * el->Align(), /* size */ 3 * el->Size(),
                        core::IOAttributes{}),
                });
        });
    }

    /// @returns true if @p composite has an element type that will need a wrapper struct
    bool ElementTypeUsesWrapperStruct(const core::type::Type* composite) {
        return tint::Switch(
            composite,
            [&](const core::type::Matrix* mat) {  //
                return (mat->Rows() == 3);
            },
            [&](const core::type::Array* arr) {
                auto* vec = arr->ElemType()->As<core::type::Vector>();
                return (vec && vec->Width() == 3);
            },
            [](Default) {  //
                return false;
            });
    }

    /// Update a @p use of an @p unpacked_type type to work with a packed type instead.
    /// @param use the use
    /// @param unpacked_type the original unpacked type
    /// @param packed_type the packed type to use instead
    void UpdateUsage(core::ir::Usage& use,
                     const core::type::Type* unpacked_type,
                     const core::type::Type* packed_type) {
        if (packed_type == unpacked_type) {
            // This type does not contain vectors that need to be packed, so there's nothing to do.
            return;
        }

        tint::Switch(
            use.instruction,
            [&](core::ir::Access* access) {  //
                UpdateAccessUsage(access, unpacked_type);
            },
            [&](core::ir::CoreBuiltinCall* call) {
                // Assume this is only `arrayLength` until we find other cases.
                TINT_ASSERT(call->Func() == core::BuiltinFn::kArrayLength);
                // Nothing to do - the arrayLength builtin does not need to access the memory.
            },
            [&](core::ir::Let* let) {
                // Propagate the packed pointer through the `let` and update its usages.
                auto* unpacked_result_type = let->Result(0)->Type();
                auto* packed_result_type = RewriteType(unpacked_result_type);
                let->Result(0)->SetType(packed_result_type);
                let->Result(0)->ForEachUseSorted([&](core::ir::Usage let_use) {  //
                    UpdateUsage(let_use, unpacked_result_type->UnwrapPtr(), packed_result_type);
                });
            },
            [&](core::ir::Load* load) {
                b.InsertAfter(load, [&] {
                    auto* result = LoadPackedToUnpacked(unpacked_type, load->From());
                    load->Result(0)->ReplaceAllUsesWith(result);
                });
                load->Destroy();
            },
            [&](core::ir::LoadVectorElement*) {
                // Nothing to do - packed vectors support component access.
            },
            [&](core::ir::Store* store) {
                b.InsertBefore(store, [&] { StoreUnpackedToPacked(store->To(), store->From()); });
                store->Destroy();
            },
            [&](core::ir::StoreVectorElement*) {
                // Nothing to do - packed vectors support component access.
            },
            [&](core::ir::UserCall*) {
                // Nothing to do - pass the packed type to the function, which will be rewritten.
            },
            TINT_ICE_ON_NO_MATCH);
    }

    /// Update an access instruction that uses an unpacked_type type to use a packed type instead.
    /// @param access the access instruction
    /// @param unpacked_type the unpacked store type of the source pointer
    void UpdateAccessUsage(core::ir::Access* access, const core::type::Type* unpacked_type) {
        auto* unpacked_result_type = access->Result(0)->Type();
        auto* packed_result_type = RewriteType(unpacked_result_type);

        // Rebuild the indices of the access instruction.
        // Walk through the intermediate types that the access chain will be traversing, and
        // check for packed vectors that would be wrapped in structures.
        auto* obj_type = unpacked_type;
        Vector<core::ir::Value*, 4> operands;
        operands.Push(access->Object());
        for (auto* idx : access->Indices()) {
            // Add the original index.
            operands.Push(idx);

            // If we are accessing into a composite that has an element type that will be
            // wrapped in a struct, we add an extra index to access into the first member of
            // that struct.
            if (ElementTypeUsesWrapperStruct(obj_type)) {
                operands.Push(b.Constant(u32(0)));
            }

            // Update the object type.
            if (auto* c = idx->As<core::ir::Constant>()) {
                obj_type = obj_type->Element(c->Value()->ValueAs<uint32_t>());
            } else {
                // Types that support dynamic indexing only have one element type.
                obj_type = obj_type->Elements().type;
            }
        }

        // Replace the access instruction's indices and update its usages.
        access->SetOperands(std::move(operands));
        access->Result(0)->SetType(packed_result_type);
        access->Result(0)->ForEachUseSorted([&](core::ir::Usage access_use) {  //
            UpdateUsage(access_use, unpacked_result_type->UnwrapPtr(), packed_result_type);
        });
    }

    /// Load a packed value from the pointer @p from and convert it to @p unpacked_type.
    ///
    /// Note: This function is called from within a builder insertion callback.
    ///
    /// @param unpacked_type the unpacked result type of the load
    /// @param from the packed pointer to load from
    /// @returns the unpacked result of the load
    core::ir::Value* LoadPackedToUnpacked(const core::type::Type* unpacked_type,
                                          core::ir::Value* from) {
        auto* packed_ptr = from->Type()->As<core::type::Pointer>();
        auto* packed_type = RewriteType(unpacked_type);
        if (unpacked_type == packed_type) {
            // There is no packed type inside `from`, so we can just load it directly.
            return b.Load(from)->Result(0);
        }

        return tint::Switch(
            unpacked_type,
            [&](const core::type::Array* arr) {
                return b.Call(LoadPackedArrayHelper(arr, packed_ptr), from)->Result(0);
            },
            [&](const core::type::Matrix* mat) {
                // Matrices are rewritten as arrays of structures, so pull the packed vectors out
                // of the structure for each column and then construct the matrix from them.
                auto* packed_col_type = RewriteType(mat->ColumnType());
                auto* packed_matrix = b.Load(from);
                Vector<core::ir::Value*, 4> columns;
                for (uint32_t col = 0; col < mat->Columns(); col++) {
                    auto* packed_col =
                        b.Access(packed_col_type, packed_matrix, u32(col), u32(0))->Result(0);
                    auto* unpacked_col = b.Convert(mat->ColumnType(), packed_col);
                    columns.Push(unpacked_col->Result(0));
                }
                return b.Construct(unpacked_type, std::move(columns))->Result(0);
            },
            [&](const core::type::Struct* str) {
                return b.Call(LoadPackedStructHelper(str, packed_ptr), from)->Result(0);
            },
            [&](const core::type::Vector*) {
                // Load the packed vector and convert it to the unpacked equivalent.
                return b.Convert(unpacked_type, b.Load(from))->Result(0);
            },
            TINT_ICE_ON_NO_MATCH);
    }

    /// Get (or create) a helper function that loads a packed array and converts it to the unpacked
    /// equivalent.
    /// @param unpacked_arr the unpacked array type
    /// @param packed_ptr_type the type of the pointer to the packed array
    /// @returns the helper function
    core::ir::Function* LoadPackedArrayHelper(const core::type::Array* unpacked_arr,
                                              const core::type::Pointer* packed_ptr_type) {
        return packed_load_helpers.GetOrAdd(unpacked_arr, [&] {
            auto* func = b.Function(sym.New("tint_load_array_packed_vec3").Name(), unpacked_arr);
            auto* from = b.FunctionParam("from", packed_ptr_type);
            func->SetParams({from});

            auto* unpacked_el_type = unpacked_arr->ElemType();
            auto* packed_el_type = RewriteType(unpacked_el_type);
            auto* packed_el_ptr_type =
                ty.ptr(packed_ptr_type->AddressSpace(), packed_el_type, packed_ptr_type->Access());

            // Check if the element is a packed vector (which will be wrapped in a structure).
            bool packed_vec = false;
            if (auto* vec = packed_el_type->As<core::type::Vector>()) {
                packed_vec = vec->Packed();
            }

            b.Append(func->Block(), [&] {
                // Helper to load an array element at a given index.
                auto load_array_element = [&](core::ir::Value* index) {
                    auto* packed_el_ptr = b.Access(packed_el_ptr_type, from, index);
                    if (packed_vec) {
                        // If the element is a packed vector it will be wrapped in a structure, so
                        // load from the first member of that structure.
                        packed_el_ptr->AddIndex(b.Constant(u32(0)));
                    }
                    return LoadPackedToUnpacked(unpacked_el_type, packed_el_ptr->Result(0));
                };

                // Array elements that are packed vectors are wrapped in structures, so pull the
                // packed vectors out of each structure and then construct the array from them.
                TINT_ASSERT(unpacked_arr->ConstantCount());
                auto count = unpacked_arr->ConstantCount().value();
                if (count <= kMaxSeriallyUnpackedArraySize) {
                    Vector<core::ir::Value*, kMaxSeriallyUnpackedArraySize> elements;
                    for (uint32_t i = 0; i < count; i++) {
                        auto* unpacked_el = load_array_element(b.Constant(u32(i)));
                        elements.Push(unpacked_el);
                    }
                    b.Return(func, b.Construct(unpacked_arr, std::move(elements)));
                } else {
                    auto* result = b.Var(ty.ptr<function>(unpacked_arr));
                    b.LoopRange(ty, u32(0), u32(count), u32(1), [&](core::ir::Value* idx) {
                        auto* to =
                            b.Access(ty.ptr(function, unpacked_arr->ElemType()), result, idx);
                        auto* unpacked_el = load_array_element(idx);
                        b.Store(to, unpacked_el);
                    });
                    b.Return(func, b.Load(result));
                }
            });

            return func;
        });
    }

    /// Get (or create) a helper function that loads a packed struct and converts it to the unpacked
    /// equivalent.
    /// @param unpacked_str the unpacked struct type
    /// @param packed_ptr_type the type of the pointer to the packed struct
    /// @returns the helper function
    core::ir::Function* LoadPackedStructHelper(const core::type::Struct* unpacked_str,
                                               const core::type::Pointer* packed_ptr_type) {
        return packed_load_helpers.GetOrAdd(unpacked_str, [&] {
            auto* func = b.Function(sym.New("tint_load_struct_packed_vec3").Name(), unpacked_str);
            auto* from = b.FunctionParam("from", packed_ptr_type);
            func->SetParams({from});

            b.Append(func->Block(), [&] {
                Vector<core::ir::Value*, 4> members;
                members.Reserve(unpacked_str->Members().Length());
                for (auto* member : unpacked_str->Members()) {
                    auto* unpacked_member_type = member->Type();
                    auto* packed_member_type = RewriteType(unpacked_member_type);
                    auto* packed_member_ptr =
                        b.Access(ty.ptr(packed_ptr_type->AddressSpace(), packed_member_type,
                                        packed_ptr_type->Access()),
                                 from, u32(member->Index()));
                    auto* unpacked_member =
                        LoadPackedToUnpacked(unpacked_member_type, packed_member_ptr->Result(0));
                    members.Push(unpacked_member);
                }
                b.Return(func, b.Construct(unpacked_str, std::move(members))->Result(0));
            });

            return func;
        });
    }

    /// Store a @p value to a pointer @p to that contains packed vectors.
    ///
    /// Note: This function is called from within a builder insertion callback.
    ///
    /// @param to the packed pointer to store to
    /// @param value the unpacked value to store
    void StoreUnpackedToPacked(core::ir::Value* to, core::ir::Value* value) {
        auto* packed_ptr = to->Type()->As<core::type::Pointer>();
        auto* unpacked_type = value->Type();
        auto* packed_type = RewriteType(unpacked_type);
        if (unpacked_type == packed_type) {
            // There is no packed type inside `value`, so we can just store it directly.
            b.Store(to, value);
            return;
        }

        tint::Switch(
            unpacked_type,
            [&](const core::type::Array* arr) {
                b.Call(StorePackedArrayHelper(arr, packed_ptr), to, value)->Result(0);
            },
            [&](const core::type::Matrix* mat) {
                // Matrices are rewritten as arrays of structures, so store the packed vectors to
                // the first member of the that structure for each column.
                auto* packed_col_type = RewriteType(mat->ColumnType());
                auto* packed_col_ptr_type =
                    ty.ptr(packed_ptr->AddressSpace(), packed_col_type, packed_ptr->Access());
                for (uint32_t col = 0; col < mat->Columns(); col++) {
                    auto* packed_col_ptr = b.Access(packed_col_ptr_type, to, u32(col), u32(0));
                    auto* unpacked_col_val = b.Access(mat->ColumnType(), value, u32(col));
                    StoreUnpackedToPacked(packed_col_ptr->Result(0), unpacked_col_val->Result(0));
                }
            },
            [&](const core::type::Struct* str) {
                b.Call(StorePackedStructHelper(str, packed_ptr), to, value)->Result(0);
            },
            [&](const core::type::Vector*) {  //
                // Convert the vector to the packed equivalent and store it.
                b.Store(to, b.Convert(packed_type, value));
            },
            TINT_ICE_ON_NO_MATCH);
    }

    /// Get (or create) a helper function that stores an unpacked array to a packed pointer.
    /// @param unpacked_arr the unpacked array type
    /// @param packed_ptr_type the type of the pointer to the packed array
    /// @returns the helper function
    core::ir::Function* StorePackedArrayHelper(const core::type::Array* unpacked_arr,
                                               const core::type::Pointer* packed_ptr_type) {
        return packed_store_helpers.GetOrAdd(unpacked_arr, [&] {
            auto* func = b.Function(sym.New("tint_store_array_packed_vec3").Name(), ty.void_());
            auto* to = b.FunctionParam("to", packed_ptr_type);
            auto* value = b.FunctionParam("value", unpacked_arr);
            func->SetParams({to, value});

            auto* unpacked_el_type = unpacked_arr->ElemType();
            auto* packed_el_type = RewriteType(unpacked_el_type);
            auto* packed_el_ptr_type =
                ty.ptr(packed_ptr_type->AddressSpace(), packed_el_type, packed_ptr_type->Access());

            // Check if the element is a packed vector (which will be wrapped in a structure).
            bool packed_vec = false;
            if (auto* vec = packed_el_type->As<core::type::Vector>()) {
                packed_vec = vec->Packed();
            }

            b.Append(func->Block(), [&] {
                // Helper to store an array element at a given index.
                auto store_array_element = [&](core::ir::Value* index) {
                    auto* unpacked_el = b.Access(unpacked_el_type, value, index);
                    auto* packed_el_ptr = b.Access(packed_el_ptr_type, to, index);
                    if (packed_vec) {
                        // If the element is a packed vector it will be wrapped in a structure, so
                        // store to the first member of that structure.
                        packed_el_ptr->AddIndex(b.Constant(u32(0)));
                    }
                    StoreUnpackedToPacked(packed_el_ptr->Result(0), unpacked_el->Result(0));
                };

                // Store to each element of the array in a loop. If the element count is below a
                // threshold, unroll that loop in the shader.
                TINT_ASSERT(unpacked_arr->ConstantCount());
                auto count = unpacked_arr->ConstantCount().value();
                if (count <= kMaxSeriallyUnpackedArraySize) {
                    for (uint32_t i = 0; i < count; i++) {
                        store_array_element(b.Constant(u32(i)));
                    }
                } else {
                    b.LoopRange(ty, u32(0), u32(count), u32(1), [&](core::ir::Value* idx) {  //
                        store_array_element(idx);
                    });
                }
                b.Return(func);
            });

            return func;
        });
    }

    /// Get (or create) a helper function that stores an unpacked struct to a packed pointer.
    /// @param unpacked_str the unpacked struct type
    /// @param packed_ptr_type the type of the pointer to the packed struct
    /// @returns the helper function
    core::ir::Function* StorePackedStructHelper(const core::type::Struct* unpacked_str,
                                                const core::type::Pointer* packed_ptr_type) {
        return packed_store_helpers.GetOrAdd(unpacked_str, [&] {
            auto* func = b.Function(sym.New("tint_store_array_packed_vec3").Name(), ty.void_());
            auto* to = b.FunctionParam("to", packed_ptr_type);
            auto* value = b.FunctionParam("value", unpacked_str);
            func->SetParams({to, value});

            b.Append(func->Block(), [&] {
                // Store each member of the structure separately.
                for (auto* member : unpacked_str->Members()) {
                    auto* unpacked_member_type = member->Type();
                    auto* packed_member_type = RewriteType(unpacked_member_type);
                    auto* unpacked_member =
                        b.Access(unpacked_member_type, value, u32(member->Index()))->Result(0);
                    auto* packed_member_ptr =
                        b.Access(ty.ptr(packed_ptr_type->AddressSpace(), packed_member_type,
                                        packed_ptr_type->Access()),
                                 to, u32(member->Index()));
                    StoreUnpackedToPacked(packed_member_ptr->Result(0), unpacked_member);
                }
                b.Return(func);
            });

            return func;
        });
    }
};

}  // namespace

Result<SuccessType> PackedVec3(core::ir::Module& ir) {
    auto result = ValidateAndDumpIfNeeded(ir, "PackedVec3 transform");
    if (result != Success) {
        return result.Failure();
    }

    State{ir}.Process();

    return Success;
}

}  // namespace tint::msl::writer::raise
