/*
 * Copyright (c) 2023 Apple Inc. All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "config.h"
#include "GlobalVariableRewriter.h"

#include "AST.h"
#include "ASTIdentifier.h"
#include "ASTVisitor.h"
#include "CallGraph.h"
#include "WGSL.h"
#include "WGSLShaderModule.h"
#include <ranges>
#include <wtf/DataLog.h>
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
#include <wtf/SetForScope.h>
#include <wtf/text/MakeString.h>

namespace WGSL {

constexpr bool shouldLogGlobalVariableRewriting = false;

class RewriteGlobalVariables : public AST::Visitor {
public:
    RewriteGlobalVariables(ShaderModule& shaderModule, const HashMap<String, PipelineLayout*>& pipelineLayouts, HashMap<String, Reflection::EntryPointInformation>& entryPointInformations)
        : AST::Visitor()
        , m_shaderModule(shaderModule)
        , m_pipelineLayouts(pipelineLayouts)
        , m_entryPointInformations(entryPointInformations)
    {
    }

    std::optional<Error> run();

    void visit(AST::Function&) override;
    void visit(AST::Variable&) override;
    void visit(AST::Parameter&) override;

    void visit(AST::CompoundStatement&) override;
    void visit(AST::AssignmentStatement&) override;
    void visit(AST::VariableStatement&) override;
    void visit(AST::PhonyAssignmentStatement&) override;
    void visit(AST::CompoundAssignmentStatement&) override;

    void visit(AST::Expression&) override;

private:
    struct Global {
        struct Resource {
            unsigned group;
            unsigned binding;
        };

        std::optional<Resource> resource;
        AST::Variable* declaration;
    };

    template<typename Value>
    using IndexMap = HashMap<uint64_t, Value, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;

    using UsedResources = IndexMap<IndexMap<Global*>>;
    using UsedPrivateGlobals = Vector<Global*>;

    struct UsedGlobals {
        UsedResources resources;
        UsedPrivateGlobals privateGlobals;
    };

    struct Insertion {
        AST::Statement* statement;
        unsigned index;
    };

    static AST::Identifier argumentBufferParameterName(unsigned group);
    static AST::Identifier dynamicOffsetVariableName();

    AST::Identifier argumentBufferStructName(unsigned group);

    void def(const AST::Identifier&, AST::Variable*);

    std::optional<Error> collectGlobals();
    std::optional<Error> visitEntryPoint(const CallGraph::EntryPoint&);
    void visitCallee(const CallGraph::Callee&);
    Result<UsedGlobals> determineUsedGlobals(const AST::Function&);
    void collectDynamicOffsetGlobals(const PipelineLayout&);
    void usesOverride(AST::Variable&);
    Vector<unsigned> insertStructs(const UsedResources&);
    Result<Vector<unsigned>> insertStructs(PipelineLayout&, const UsedResources&);
    AST::StructureMember& createArgumentBufferEntry(unsigned binding, AST::Variable&);
    AST::StructureMember& createArgumentBufferEntry(unsigned binding, const SourceSpan&, const String& name, AST::Expression& type);
    void finalizeArgumentBufferStruct(unsigned group, Vector<std::pair<unsigned, AST::StructureMember*>>&);
    void insertDynamicOffsetsBufferIfNeeded(const AST::Function&);
    void insertDynamicOffsetsBufferIfNeeded(const SourceSpan&, const AST::Function&);
    void insertParameter(const SourceSpan&, const AST::Function&, unsigned, AST::Identifier&&, AST::Expression* = nullptr, AST::ParameterRole = AST::ParameterRole::BindGroup);

    void insertParameters(AST::Function&, const Vector<unsigned>&);
    void insertMaterializations(AST::Function&, const UsedResources&);
    void insertLocalDefinitions(AST::Function&, const UsedPrivateGlobals&);
    const Global* readVariable(AST::IdentifierExpression&);
    void insertBeforeCurrentStatement(AST::Statement&);
    AST::Expression& bufferLengthType();
    AST::Expression& bufferLengthReferenceType();

    // zero initialization
    void initializeVariables(AST::Function&, const UsedPrivateGlobals&, size_t);
    void insertWorkgroupBarrier(AST::Function&, size_t);
    AST::Identifier& findOrInsertLocalInvocationIndex(AST::Function&);
    AST::Statement::List storeInitialValue(const UsedPrivateGlobals&);
    void storeInitialValue(AST::Expression&, AST::Statement::List&, unsigned);

    void packResource(AST::Variable&);
    void packArrayResource(AST::Variable&, const Types::Array*);
    void packStructResource(AST::Variable&, const Types::Struct*);
    const Type* packType(const Type*);
    const Type* packStructType(const Types::Struct*);
    const Type* packArrayType(const Types::Array*);
    void updateReference(AST::Variable&, AST::Expression&);

    Packing pack(Packing, AST::Expression&);
    Packing getPacking(AST::IdentifierExpression&);
    Packing getPacking(AST::FieldAccessExpression&);
    Packing getPacking(AST::IndexAccessExpression&);
    Packing getPacking(AST::BinaryExpression&);
    Packing getPacking(AST::UnaryExpression&);
    Packing getPacking(AST::CallExpression&);
    Packing getPacking(AST::IdentityExpression&);
    Packing packingForType(const Type*);

    AST::IdentifierExpression& getBase(AST::Expression&, unsigned&);

    ShaderModule& m_shaderModule;
    HashMap<String, Global> m_globals;
    HashMap<std::tuple<unsigned, unsigned>, AST::Variable*> m_globalsByBinding;
    IndexMap<Vector<std::pair<unsigned, String>>> m_groupBindingMap;
    IndexMap<const Type*> m_structTypes;
    HashMap<String, AST::Variable*> m_defs;
    ListHashSet<String> m_reads;
    HashMap<AST::Function*, ListHashSet<String>> m_lengthParameters;
    HashMap<AST::Function*, ListHashSet<String>> m_visitedFunctions;
    Reflection::EntryPointInformation* m_entryPointInformation { nullptr };
    HashMap<uint32_t, uint32_t, DefaultHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_generateLayoutGroupMapping;
    PipelineLayout* m_generatedLayout { nullptr };
    unsigned m_constantId { 0 };
    unsigned m_currentStatementIndex { 0 };
    unsigned m_entryPointID { 0 };
    Vector<Insertion> m_pendingInsertions;
    HashMap<const Types::Struct*, const Type*> m_packedStructTypes;
    ShaderStage m_stage { ShaderStage::Vertex };
    const HashMap<String, PipelineLayout*>& m_pipelineLayouts;
    HashMap<String, Reflection::EntryPointInformation>& m_entryPointInformations;
    HashMap<AST::Variable*, AST::Variable*> m_bufferLengthMap;
    HashMap<AST::Variable*, AST::Variable*> m_reverseBufferLengthMap;
    AST::Expression* m_bufferLengthType { nullptr };
    AST::Expression* m_bufferLengthReferenceType { nullptr };
    AST::Function* m_currentFunction { nullptr };
    HashMap<std::pair<unsigned, unsigned>, unsigned> m_globalsUsingDynamicOffset;
    HashSet<AST::Expression*> m_doNotUnpack;
    CheckedUint32 m_combinedFunctionVariablesSize;
};

std::optional<Error> RewriteGlobalVariables::run()
{
    dataLogLnIf(shouldLogGlobalVariableRewriting, "BEGIN: GlobalVariableRewriter");

    if (auto error = collectGlobals())
        return error;
    for (auto& entryPoint : m_shaderModule.callGraph().entrypoints()) {
        auto maybeError = visitEntryPoint(entryPoint);
        ++m_entryPointID;
        if (maybeError.has_value())
            return maybeError;
    }

    dataLogLnIf(shouldLogGlobalVariableRewriting, "END: GlobalVariableRewriter");
    return std::nullopt;
}

void RewriteGlobalVariables::visitCallee(const CallGraph::Callee& callee)
{
    const auto& updateCallee = [&] {
        for (auto& read : m_reads) {
            auto it = m_globals.find(read);
            RELEASE_ASSERT(it != m_globals.end());
            auto& global = it->value;
            AST::Expression* type;
            if (global.declaration->flavor() == AST::VariableFlavor::Var)
                type = global.declaration->maybeReferenceType();
            else {
                ASSERT(global.declaration->flavor() == AST::VariableFlavor::Override);
                type = global.declaration->maybeTypeName();
                if (!type) {
                    auto* storeType = global.declaration->storeType();
                    auto& typeExpression = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make(storeType->toString()));
                    typeExpression.m_inferredType = storeType;
                    type = &typeExpression;
                }
            }
            ASSERT(type);

            auto parameterRole = global.declaration->role() == AST::VariableRole::PackedResource ? AST::ParameterRole::PackedResource : AST::ParameterRole::UserDefined;
            m_shaderModule.append(callee.target->parameters(), m_shaderModule.astBuilder().construct<AST::Parameter>(
                SourceSpan::empty(),
                AST::Identifier::make(read),
                *type,
                AST::Attribute::List { },
                parameterRole
            ));
        }

        auto it = m_lengthParameters.find(callee.target);
        if (it != m_lengthParameters.end() && !it->value.isEmpty()) {
            auto& lengthType = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("u32"_s));
            lengthType.m_inferredType = m_shaderModule.types().u32Type();

            for (auto& length : it->value) {
                auto lengthName = makeString("__"_s, length, "_ArrayLength"_s);
                if (m_reads.contains(lengthName))
                    continue;
                m_shaderModule.append(callee.target->parameters(), m_shaderModule.astBuilder().construct<AST::Parameter>(
                    SourceSpan::empty(),
                    AST::Identifier::make(lengthName),
                    lengthType,
                    AST::Attribute::List { },
                    AST::ParameterRole::UserDefined
                ));
            }
        }
    };

    const auto& updateCallSites = [&] {
        for (auto& read : m_reads) {
            for (auto& [_, call] : callee.callSites) {
                auto it = m_globals.find(read);
                RELEASE_ASSERT(it != m_globals.end());
                auto& global = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
                    SourceSpan::empty(),
                    AST::Identifier::make(read)
                );
                global.m_inferredType = it->value.declaration->storeType();
                m_shaderModule.append(call->arguments(), global);
                m_doNotUnpack.add(&global);
            }
        }

        auto it = m_lengthParameters.find(callee.target);
        if (it != m_lengthParameters.end() && !it->value.isEmpty()) {
            auto& lengthType = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("u32"_s));
            lengthType.m_inferredType = m_shaderModule.types().u32Type();

            for (auto& lengthParameter : it->value) {
                auto lengthName = makeString("__"_s, lengthParameter, "_ArrayLength"_s);
                if (m_reads.contains(lengthName))
                    continue;

                unsigned index = 0;
                for (auto& parameter : callee.target->parameters()) {
                    if (parameter.name() == lengthParameter)
                        break;
                    ++index;
                }
                for (auto& [caller, call] : callee.callSites) {
                    auto& argument = call->arguments()[index];
                    unsigned arrayOffset = 0;
                    auto& base = getBase(argument, arrayOffset);
                    auto& identifier = base.identifier();

                    auto result = m_lengthParameters.add(caller, ListHashSet<String> { });
                    result.iterator->value.add(identifier);

                    auto lengthName = makeString("__"_s, identifier, "_ArrayLength"_s);
                    auto& length = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
                        SourceSpan::empty(),
                        AST::Identifier::make(lengthName)
                    );
                    length.m_inferredType = m_shaderModule.types().u32Type();
                    AST::Expression* lhs = &length;
                    if (arrayOffset) {
                        auto& arrayOffsetExpression = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
                            SourceSpan::empty(),
                            arrayOffset
                        );
                        arrayOffsetExpression.m_inferredType = m_shaderModule.types().u32Type();
                        lhs = &m_shaderModule.astBuilder().construct<AST::BinaryExpression>(
                            SourceSpan::empty(),
                            length,
                            arrayOffsetExpression,
                            AST::BinaryOperation::Subtract
                        );
                        lhs->m_inferredType = m_shaderModule.types().u32Type();
                    }
                    m_shaderModule.append(call->arguments(), *lhs);
                }
            }
        }
    };

    auto it = m_visitedFunctions.find(callee.target);
    if (it != m_visitedFunctions.end()) {
        dataLogLnIf(shouldLogGlobalVariableRewriting, "> Already visited callee: ", callee.target->name());
        m_reads = it->value;
        updateCallSites();
        return;
    }

    dataLogLnIf(shouldLogGlobalVariableRewriting, "> Visiting callee: ", callee.target->name());

    visit(*callee.target);
    updateCallee();
    updateCallSites();

    m_visitedFunctions.add(callee.target, m_reads);
}

void RewriteGlobalVariables::visit(AST::Function& function)
{
    ListHashSet<String> reads;
    for (auto& callee : m_shaderModule.callGraph().callees(function)) {
        visitCallee(callee);

        if (hasError())
            return;

        for (const auto& read : m_reads)
            reads.add(read);
    }
    m_reads = WTFMove(reads);
    m_defs.clear();
    m_combinedFunctionVariablesSize = 0;

    def(function.name(), nullptr);
    m_currentFunction = &function;
    AST::Visitor::visit(function);
    m_currentFunction = nullptr;

    // https://www.w3.org/TR/WGSL/#limits
    constexpr unsigned maximumCombinedFunctionVariablesSize = 8192;
    if (m_combinedFunctionVariablesSize.hasOverflowed() || m_combinedFunctionVariablesSize.value() > maximumCombinedFunctionVariablesSize) [[unlikely]]
        setError(Error(makeString("The combined byte size of all variables in this function exceeds "_s, String::number(maximumCombinedFunctionVariablesSize), " bytes"_s), function.span()));
}

void RewriteGlobalVariables::visit(AST::Parameter& parameter)
{
    def(parameter.name(), nullptr);
    AST::Visitor::visit(parameter);
}

void RewriteGlobalVariables::visit(AST::Variable& variable)
{
    def(variable.name(), &variable);
    AST::Visitor::visit(variable);
}

void RewriteGlobalVariables::visit(AST::CompoundStatement& statement)
{
    auto indexScope = SetForScope(m_currentStatementIndex, 0);
    auto insertionScope = SetForScope(m_pendingInsertions, Vector<Insertion>());

    for (auto& statement : statement.statements()) {
        AST::Visitor::visit(statement);
        ++m_currentStatementIndex;
    }

    unsigned offset = 0;
    for (auto& insertion : m_pendingInsertions) {
        m_shaderModule.insert(statement.statements(), insertion.index + offset, AST::Statement::Ref(*insertion.statement));
        ++offset;
    }
}

void RewriteGlobalVariables::visit(AST::CompoundAssignmentStatement& statement)
{
    Packing lhsPacking = pack(Packing::Unpacked, statement.leftExpression());
    pack(lhsPacking, statement.rightExpression());
}

void RewriteGlobalVariables::visit(AST::AssignmentStatement& statement)
{
    Packing lhsPacking = pack(Packing::Either, statement.lhs());
    ASSERT(lhsPacking != Packing::Either);
    if (lhsPacking == Packing::PackedVec3)
        lhsPacking = Packing::Either;
    pack(lhsPacking, statement.rhs());
}

void RewriteGlobalVariables::visit(AST::VariableStatement& statement)
{
    if (statement.variable().flavor() == AST::VariableFlavor::Var)
        m_combinedFunctionVariablesSize += statement.variable().storeType()->size();
    if (auto* initializer = statement.variable().maybeInitializer())
        pack(static_cast<Packing>(Packing::Unpacked), *initializer);
}

void RewriteGlobalVariables::visit(AST::PhonyAssignmentStatement& statement)
{
    pack(Packing::Either, statement.rhs());
}

void RewriteGlobalVariables::visit(AST::Expression& expression)
{
    pack(Packing::Unpacked, expression);
}

Packing RewriteGlobalVariables::pack(Packing expectedPacking, AST::Expression& expression)
{
    if (m_doNotUnpack.contains(&expression))
        return expectedPacking;

    const auto& visitAndReplace = [&](auto& expression) -> Packing {
        auto packing = getPacking(expression);
        if (expectedPacking & packing)
            return packing;

        auto* type = expression.inferredType();
        if (auto* referenceType = std::get_if<Types::Reference>(type))
            type = referenceType->element;
        ASCIILiteral operation;
        if (std::holds_alternative<Types::Struct>(*type)) {
            if (!type->isConstructible())
                return packing;
            operation = packing & Packing::Packed ? "__unpack"_s : "__pack"_s;
        } else if (std::holds_alternative<Types::Array>(*type)) {
            if (packing & Packing::Packed) {
                operation = "__unpack"_s;
                m_shaderModule.setUsesUnpackArray();
            } else {
                operation = "__pack"_s;
                m_shaderModule.setUsesPackArray();
            }
        } else {
            if (packing & Packing::Packed) {
                operation = "__unpack"_s;
                m_shaderModule.setUsesUnpackVector();
            } else {
                operation = "__pack"_s;
                m_shaderModule.setUsesPackVector();
            }
        }
        RELEASE_ASSERT(!operation.isNull());
        auto& callee = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
            SourceSpan::empty(),
            AST::Identifier::make(operation)
        );
        callee.m_inferredType = m_shaderModule.types().u32Type();
        auto& argument = m_shaderModule.astBuilder().construct<std::remove_cvref_t<decltype(expression)>>(expression);
        auto& call = m_shaderModule.astBuilder().construct<AST::CallExpression>(
            SourceSpan::empty(),
            callee,
            AST::Expression::List { argument }
        );
        call.m_inferredType = argument.inferredType();
        m_shaderModule.replace(expression, call);
        return static_cast<Packing>(Packing::Either ^ packing);
    };

    switch (expression.kind()) {
    case AST::NodeKind::IdentifierExpression:
        return visitAndReplace(uncheckedDowncast<AST::IdentifierExpression>(expression));
    case AST::NodeKind::FieldAccessExpression:
        return visitAndReplace(uncheckedDowncast<AST::FieldAccessExpression>(expression));
    case AST::NodeKind::IndexAccessExpression:
        return visitAndReplace(uncheckedDowncast<AST::IndexAccessExpression>(expression));
    case AST::NodeKind::BinaryExpression:
        return visitAndReplace(uncheckedDowncast<AST::BinaryExpression>(expression));
    case AST::NodeKind::UnaryExpression:
        return visitAndReplace(uncheckedDowncast<AST::UnaryExpression>(expression));
    case AST::NodeKind::CallExpression:
        return visitAndReplace(uncheckedDowncast<AST::CallExpression>(expression));
    case AST::NodeKind::IdentityExpression:
        return visitAndReplace(uncheckedDowncast<AST::IdentityExpression>(expression));
    default:
        AST::Visitor::visit(expression);
        return Packing::Unpacked;
    }
}

Packing RewriteGlobalVariables::getPacking(AST::IdentifierExpression& identifier)
{
    auto* global = readVariable(identifier);
    if (global && global->resource.has_value())
        return packingForType(identifier.inferredType());

    return Packing::Unpacked;
}

Packing RewriteGlobalVariables::getPacking(AST::FieldAccessExpression& expression)
{
    auto* baseType = expression.base().inferredType();
    if (!baseType) {
        // All AST nodes should have an inferred type, but we create field
        // access nodes from the EntryPointRewriter which don't have a trivial
        // type, so we work around it by returning unpacked since those are only
        // used for marshalling inputs/outputs and don't need to packed/unpacked.
        return Packing::Unpacked;
    }

    if (auto* referenceType = std::get_if<Types::Reference>(baseType))
        baseType = referenceType->element;

    bool isPointer = false;
    if (auto* pointerType = std::get_if<Types::Pointer>(baseType)) {
        isPointer = true;
        baseType = pointerType->element;
    }

    if (std::holds_alternative<Types::Vector>(*baseType)) {
        if (std::holds_alternative<Types::Vector>(*expression.inferredType())) {
            if (isPointer) {
                auto& dereference = m_shaderModule.astBuilder().construct<AST::UnaryExpression>(
                    expression.base().span(),
                    expression.base(),
                    AST::UnaryOperation::Dereference
                );
                dereference.m_inferredType = baseType;

                auto& fieldAccessExpression = m_shaderModule.astBuilder().construct<AST::FieldAccessExpression>(
                    expression.span(),
                    dereference,
                    AST::Identifier::make(expression.fieldName())
                );
                fieldAccessExpression.m_inferredType = expression.inferredType();

                m_shaderModule.replace(expression, fieldAccessExpression);
            }
            pack(Packing::Unpacked, expression.base());
        } else
            pack(Packing::Either, expression.base());
        return Packing::Unpacked;
    }

    auto basePacking = pack(Packing::Either, expression.base());
    if (basePacking & Packing::Unpacked)
        return Packing::Unpacked;

    ASSERT(std::holds_alternative<Types::Struct>(*baseType));
    auto& structType = std::get<Types::Struct>(*baseType);
    auto* fieldType = structType.fields.get(expression.originalFieldName());
    return packingForType(fieldType);
}

Packing RewriteGlobalVariables::getPacking(AST::IndexAccessExpression& expression)
{
    auto basePacking = pack(Packing::Either, expression.base());
    pack(Packing::Unpacked, expression.index());
    if (basePacking & Packing::Unpacked)
        return Packing::Unpacked;
    auto* baseType = expression.base().inferredType();
    if (auto* referenceType = std::get_if<Types::Reference>(baseType))
        baseType = referenceType->element;
    if (auto* pointerType = std::get_if<Types::Pointer>(baseType))
        baseType = pointerType->element;
    if (std::holds_alternative<Types::Vector>(*baseType))
        return Packing::Unpacked;
    ASSERT(std::holds_alternative<Types::Array>(*baseType));
    auto& arrayType = std::get<Types::Array>(*baseType);
    return packingForType(arrayType.element);
}

Packing RewriteGlobalVariables::getPacking(AST::BinaryExpression& expression)
{
    pack(Packing::Unpacked, expression.leftExpression());
    pack(Packing::Unpacked, expression.rightExpression());
    return Packing::Unpacked;
}

Packing RewriteGlobalVariables::getPacking(AST::UnaryExpression& expression)
{
    if (expression.operation() == AST::UnaryOperation::AddressOf) {
        pack(Packing::Either, expression.expression());
        // we can't pack/unpack pointers, so we return Either to avoid that
        return Packing::Either;
    }
    if (expression.operation() == AST::UnaryOperation::Dereference) {
        // similarly to above, pointers are handled differently, so we can't trust
        // the packing of the underlying element and instead we skip any packing
        // of the operand (since we can't pack/unpack pointers) and return the
        // packing of the resulting type from dereferencing
        pack(Packing::Either, expression.expression());
        auto* pointer = std::get_if<Types::Pointer>(expression.expression().inferredType());
        if (pointer->addressSpace == AddressSpace::Storage || pointer->addressSpace == AddressSpace::Uniform)
            return expression.inferredType()->packing();
        return Packing::Unpacked;
    }
    return pack(Packing::Unpacked, expression.expression());
}

Packing RewriteGlobalVariables::getPacking(AST::IdentityExpression& expression)
{
    return pack(Packing::Either, expression.expression());
}

Packing RewriteGlobalVariables::getPacking(AST::CallExpression& call)
{
    if (auto target = dynamicDowncast<AST::IdentifierExpression>(call.target())) {
        if (target->identifier() == "arrayLength"_s) {
            ASSERT(call.arguments().size() == 1);
            auto& arrayPointer = call.arguments()[0];
            unsigned arrayOffset = 0;
            auto& base = getBase(arrayPointer, arrayOffset);
            auto& identifier = base.identifier();
            if (!m_globals.contains(identifier)) {
                auto result = m_lengthParameters.add(m_currentFunction, ListHashSet<String> { });
                result.iterator->value.add(identifier);
            }
            auto lengthName = makeString("__"_s, identifier, "_ArrayLength"_s);
            auto& length = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
                SourceSpan::empty(),
                AST::Identifier::make(lengthName)
            );
            length.m_inferredType = m_shaderModule.types().u32Type();

            auto* arrayPointerType = arrayPointer.inferredType();
            ASSERT(std::holds_alternative<Types::Pointer>(*arrayPointerType));
            auto& arrayType = std::get<Types::Pointer>(*arrayPointerType).element;
            ASSERT(std::holds_alternative<Types::Array>(*arrayType));
            auto* elementType = std::get<Types::Array>(*arrayType).element;
            auto arrayStride = elementType->size();
            arrayStride = WTF::roundUpToMultipleOf(elementType->alignment(), arrayStride);

            auto& strideExpression = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
                SourceSpan::empty(),
                arrayStride
            );
            strideExpression.m_inferredType = m_shaderModule.types().u32Type();

            AST::Expression* lhs = &length;
            if (arrayOffset) {
                auto& arrayOffsetExpression = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
                    SourceSpan::empty(),
                    arrayOffset
                );
                arrayOffsetExpression.m_inferredType = m_shaderModule.types().u32Type();
                lhs = &m_shaderModule.astBuilder().construct<AST::BinaryExpression>(
                    SourceSpan::empty(),
                    length,
                    arrayOffsetExpression,
                    AST::BinaryOperation::Subtract
                );
                lhs->m_inferredType = m_shaderModule.types().u32Type();
            }

            m_shaderModule.setUsesDivision();
            auto& elementCount = m_shaderModule.astBuilder().construct<AST::BinaryExpression>(
                SourceSpan::empty(),
                *lhs,
                strideExpression,
                AST::BinaryOperation::Divide
            );
            elementCount.m_inferredType = m_shaderModule.types().u32Type();

            m_shaderModule.replace(call, elementCount);
            // mark both the array and array length as read
            readVariable(base);
            readVariable(length);
            return Packing::Unpacked;
        }
    }

    for (auto& argument : call.arguments())
        pack(Packing::Unpacked, argument);
    return Packing::Unpacked;
}

Packing RewriteGlobalVariables::packingForType(const Type* type)
{
    return type->packing();
}

AST::IdentifierExpression& RewriteGlobalVariables::getBase(AST::Expression& expression, unsigned& arrayOffset)
{
    if (auto* identityExpression = dynamicDowncast<AST::IdentityExpression>(expression))
        return getBase(identityExpression->expression(), arrayOffset);
    if (auto* unaryExpression = dynamicDowncast<AST::UnaryExpression>(expression))
        return getBase(unaryExpression->expression(), arrayOffset);
    if (auto* fieldAccess = dynamicDowncast<AST::FieldAccessExpression>(expression)) {
        auto& base = fieldAccess->base();
        auto* type = base.inferredType();
        if (auto* reference = std::get_if<Types::Reference>(type))
            type = reference->element;
        if (auto* pointer = std::get_if<Types::Pointer>(type))
            type = pointer->element;
        auto& structure = std::get<Types::Struct>(*type).structure;
        auto& lastMember = structure.members().last();
        RELEASE_ASSERT(lastMember.name().id() == fieldAccess->fieldName().id());
        arrayOffset += lastMember.offset();
        return getBase(base, arrayOffset);
    }
    if (auto* identifierExpression = dynamicDowncast<AST::IdentifierExpression>(expression))
        return *identifierExpression;
    RELEASE_ASSERT_NOT_REACHED();
}

static unsigned buffersForStage(const Configuration& configuration, ShaderStage stage)
{
    switch (stage) {
    case ShaderStage::Compute:
        return configuration.maxBuffersForComputeStage;
    case ShaderStage::Vertex:
        return configuration.maxBuffersPlusVertexBuffersForVertexStage;
    case ShaderStage::Fragment:
        return configuration.maxBuffersForFragmentStage;
    }
}

std::optional<Error> RewriteGlobalVariables::collectGlobals()
{
    Vector<std::tuple<AST::Variable*, unsigned>> bufferLengths;
    // we can't use a range-based for loop here since we might create new structs
    // and insert them into the declarations vector
    auto size = m_shaderModule.declarations().size();
    for (unsigned i = 0; i < size; ++i) {
        auto* globalVar = dynamicDowncast<AST::Variable>(m_shaderModule.declarations()[i]);
        if (!globalVar)
            continue;
        std::optional<Global::Resource> resource;
        if (globalVar->group().has_value()) {
            RELEASE_ASSERT(globalVar->binding().has_value());
            unsigned bufferIndex = *globalVar->group();
            auto buffersCountForStage = buffersForStage(m_shaderModule.configuration(), m_stage);
            if (bufferIndex >= buffersCountForStage)
                return Error(makeString("global has buffer index "_s, bufferIndex, " which exceeds the max allowed buffer index "_s, buffersCountForStage, " for this stage"_s), SourceSpan::empty());

            resource = { *globalVar->group(), *globalVar->binding() };
        }

        dataLogLnIf(shouldLogGlobalVariableRewriting, "> Found global: ", globalVar->name(), ", isResource: ", resource.has_value() ? "yes" : "no");

        auto result = m_globals.add(globalVar->name(), Global {
            resource,
            globalVar
        });
        ASSERT_UNUSED(result, result.isNewEntry);

        if (resource.has_value()) {
            m_globalsByBinding.add({ resource->group + 1, resource->binding + 1 }, globalVar);

            auto result = m_groupBindingMap.add(resource->group, Vector<std::pair<unsigned, String>>());
            result.iterator->value.append({ resource->binding, globalVar->name() });
            packResource(*globalVar);

            bufferLengths.append({ globalVar, resource->group });
        }
    }

    for (auto& [_, vector] : m_groupBindingMap)
        std::ranges::sort(vector, { }, &std::pair<unsigned, String>::first);

    if (!bufferLengths.isEmpty()) {
        for (const auto& [variable, group] : bufferLengths) {
            auto name = AST::Identifier::make(makeString("__"_s, variable->name(), "_ArrayLength"_s));
            auto& lengthVariable = m_shaderModule.astBuilder().construct<AST::Variable>(
                SourceSpan::empty(),
                AST::VariableFlavor::Var,
                AST::Identifier::make(name),
                &bufferLengthType(),
                nullptr
            );
            lengthVariable.m_referenceType = &bufferLengthReferenceType();

            auto it = m_groupBindingMap.find(group);
            ASSERT(it != m_groupBindingMap.end());

            auto binding = it->value.last().first + 1;
            it->value.append({ binding, name });

            auto result = m_globals.add(name, Global {
                { {
                    group,
                    binding,
                } },
                &lengthVariable
            });
            ASSERT_UNUSED(result, result.isNewEntry);

            m_bufferLengthMap.add(variable, &lengthVariable);
            m_reverseBufferLengthMap.add(&lengthVariable, variable);
        }
    }

    return std::nullopt;
}

AST::Expression& RewriteGlobalVariables::bufferLengthType()
{
    if (m_bufferLengthType)
        return *m_bufferLengthType;
    m_bufferLengthType = &m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("u32"_s));
    m_bufferLengthType->m_inferredType = m_shaderModule.types().u32Type();
    return *m_bufferLengthType;
}

AST::Expression& RewriteGlobalVariables::bufferLengthReferenceType()
{
    if (m_bufferLengthReferenceType)
        return *m_bufferLengthReferenceType;

    m_bufferLengthReferenceType = &m_shaderModule.astBuilder().construct<AST::ReferenceTypeExpression>(
        SourceSpan::empty(),
        bufferLengthType()
    );
    m_bufferLengthReferenceType->m_inferredType = m_shaderModule.types().referenceType(AddressSpace::Handle, m_shaderModule.types().u32Type(), AccessMode::Read);
    return *m_bufferLengthReferenceType;
}

void RewriteGlobalVariables::packResource(AST::Variable& global)
{
    auto* maybeTypeName = global.maybeTypeName();
    ASSERT(maybeTypeName);

    auto* resolvedType = maybeTypeName->inferredType();
    if (auto* arrayType = std::get_if<Types::Array>(resolvedType)) {
        packArrayResource(global, arrayType);
        return;
    }

    if (auto* structType = std::get_if<Types::Struct>(resolvedType)) {
        packStructResource(global, structType);
        return;
    }
}

void RewriteGlobalVariables::packStructResource(AST::Variable& global, const Types::Struct* structType)
{
    const Type* packedStructType = packStructType(structType);
    if (!packedStructType)
        return;

    auto& packedType = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
        SourceSpan::empty(),
        AST::Identifier::make(std::get<Types::Struct>(*packedStructType).structure.name().id())
    );
    packedType.m_inferredType = packedStructType;
    auto& namedTypeName = downcast<AST::IdentifierExpression>(*global.maybeTypeName());
    m_shaderModule.replace(namedTypeName, packedType);
    updateReference(global, packedType);
    m_shaderModule.replace(&global.role(), AST::VariableRole::PackedResource);
}

void RewriteGlobalVariables::packArrayResource(AST::Variable& global, const Types::Array* arrayType)
{
    const Type* packedArrayType = packArrayType(arrayType);
    if (!packedArrayType)
        return;

    const Type* packedElementType = std::get<Types::Array>(*packedArrayType).element;
    auto& packedType = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
        SourceSpan::empty(),
        AST::Identifier::make("__PackedArray"_s) // This name is not used by the codegen
    );
    packedType.m_inferredType = packedElementType;

    auto& arrayTypeName = downcast<AST::ArrayTypeExpression>(*global.maybeTypeName());
    auto& packedArrayTypeName = m_shaderModule.astBuilder().construct<AST::ArrayTypeExpression>(
        arrayTypeName.span(),
        &packedType,
        arrayTypeName.maybeElementCount()
    );
    packedArrayTypeName.m_inferredType = packedArrayType;

    m_shaderModule.replace(arrayTypeName, packedArrayTypeName);
    updateReference(global, packedArrayTypeName);
    m_shaderModule.replace(&global.role(), AST::VariableRole::PackedResource);
}

void RewriteGlobalVariables::updateReference(AST::Variable& global, AST::Expression& packedType)
{
    auto* maybeReference = global.maybeReferenceType();
    ASSERT(maybeReference);
    auto& reference = downcast<AST::ReferenceTypeExpression>(*maybeReference);
    auto* referenceType = std::get_if<Types::Reference>(reference.inferredType());
    ASSERT(referenceType);
    auto& packedTypeReference = m_shaderModule.astBuilder().construct<AST::ReferenceTypeExpression>(
        SourceSpan::empty(),
        packedType
    );
    packedTypeReference.m_inferredType = m_shaderModule.types().referenceType(
        referenceType->addressSpace,
        packedType.inferredType(),
        referenceType->accessMode
    );
    m_shaderModule.replace(reference, packedTypeReference);
}

const Type* RewriteGlobalVariables::packType(const Type* type)
{
    if (auto* structType = std::get_if<Types::Struct>(type))
        return packStructType(structType);
    if (auto* arrayType = std::get_if<Types::Array>(type))
        return packArrayType(arrayType);
    if (auto* vectorType = std::get_if<Types::Vector>(type)) {
        if (vectorType->size == 3) {
            m_shaderModule.setUsesPackedVec3();
            return type;
        }
    }
    return nullptr;
}

const Type* RewriteGlobalVariables::packStructType(const Types::Struct* structType)
{
    if (structType->structure.role() == AST::StructureRole::UserDefinedResource)
        return m_packedStructTypes.get(structType);

    // Ensure we pack nested structs
    bool packedAnyMember = false;
    for (auto& member : structType->structure.members()) {
        if (packType(member.type().inferredType()))
            packedAnyMember = true;
    }
    if (!packedAnyMember && !structType->structure.hasSizeOrAlignmentAttributes())
        return nullptr;

    ASSERT(structType->structure.role() == AST::StructureRole::UserDefined);
    m_shaderModule.replace(&structType->structure.role(), AST::StructureRole::UserDefinedResource);

    String packedStructName = makeString("__"_s, structType->structure.name(), "_Packed"_s);

    auto& packedStruct = m_shaderModule.astBuilder().construct<AST::Structure>(
        SourceSpan::empty(),
        AST::Identifier::make(packedStructName),
        AST::StructureMember::List(structType->structure.members()),
        AST::Attribute::List { },
        AST::StructureRole::PackedResource,
        &structType->structure
    );
    m_shaderModule.append(m_shaderModule.declarations(), packedStruct);
    const Type* packedStructType = m_shaderModule.types().structType(packedStruct);
    packedStruct.m_inferredType = packedStructType;
    m_packedStructTypes.add(structType, packedStructType);
    return packedStructType;
}

const Type* RewriteGlobalVariables::packArrayType(const Types::Array* arrayType)
{
    auto* packedElementType = packType(arrayType->element);
    if (!packedElementType)
        return nullptr;

    m_shaderModule.setUsesUnpackArray();
    m_shaderModule.setUsesPackArray();
    return m_shaderModule.types().arrayType(packedElementType, arrayType->size);
}

static size_t getRoundedSize(const AST::Variable& variable)
{
    auto* type = variable.storeType();
    return roundUpToMultipleOf(16, type ? type->size() : 0);
}

void RewriteGlobalVariables::insertParameter(const SourceSpan& span, const AST::Function& function, unsigned group, AST::Identifier&& name, AST::Expression* type, AST::ParameterRole parameterRole)
{
    if (!type) {
        type = &m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(span, argumentBufferStructName(group));
        type->m_inferredType = m_structTypes.get(group);
    }
    auto& groupValue = m_shaderModule.astBuilder().construct<AST::AbstractIntegerLiteral>(span, group);
    groupValue.m_inferredType = m_shaderModule.types().abstractIntType();
    groupValue.setConstantValue(group);
    auto& groupAttribute = m_shaderModule.astBuilder().construct<AST::GroupAttribute>(span, groupValue);
    m_shaderModule.append(function.parameters(), m_shaderModule.astBuilder().construct<AST::Parameter>(
        span,
        WTFMove(name),
        *type,
        AST::Attribute::List { groupAttribute },
        parameterRole
    ));
};

std::optional<Error> RewriteGlobalVariables::visitEntryPoint(const CallGraph::EntryPoint& entryPoint)
{
    dataLogLnIf(shouldLogGlobalVariableRewriting, "> Visiting entrypoint: ", entryPoint.function.name());

    auto it = m_pipelineLayouts.find(entryPoint.originalName);
    if (it == m_pipelineLayouts.end())
        return std::nullopt;

    m_reads.clear();
    m_structTypes.clear();
    m_globalsUsingDynamicOffset.clear();
    m_generateLayoutGroupMapping.clear();

    auto result = m_entryPointInformations.add(entryPoint.originalName, Reflection::EntryPointInformation { });
    RELEASE_ASSERT(result.isNewEntry);

    m_stage = entryPoint.stage;
    m_entryPointInformation = &result.iterator->value;
    m_entryPointInformation->originalName = entryPoint.originalName;
    m_entryPointInformation->mangledName = entryPoint.function.name();

    switch (m_stage) {
    case ShaderStage::Compute: {
        for (auto& attribute : entryPoint.function.attributes()) {
            auto* workgroupSize = dynamicDowncast<AST::WorkgroupSizeAttribute>(attribute);
            if (!workgroupSize)
                continue;
            m_entryPointInformation->typedEntryPoint = Reflection::Compute { &workgroupSize->x(), workgroupSize->maybeY(), workgroupSize->maybeZ() };
            break;
        }
        break;
    }
    case ShaderStage::Vertex:
        m_entryPointInformation->typedEntryPoint = Reflection::Vertex { false };
        break;
    case ShaderStage::Fragment:
        m_entryPointInformation->typedEntryPoint = Reflection::Fragment { };
        break;
    }


    if (!it->value) {
        m_entryPointInformation->defaultLayout = { PipelineLayout { } };
        m_generatedLayout = &*m_entryPointInformation->defaultLayout;
    } else {
        m_generatedLayout = nullptr;
        collectDynamicOffsetGlobals(*it->value);
    }

    visit(entryPoint.function);
    if (hasError())
        return AST::Visitor::result().error();

    if (m_reads.isEmpty()) {
        insertDynamicOffsetsBufferIfNeeded(entryPoint.function);
        return std::nullopt;
    }

    auto maybeUsedGlobals = determineUsedGlobals(entryPoint.function);
    if (!maybeUsedGlobals) {
        insertDynamicOffsetsBufferIfNeeded(entryPoint.function);
        return maybeUsedGlobals.error();
    }
    auto usedGlobals = *maybeUsedGlobals;
    auto maybeGroups = m_generatedLayout ? Result<Vector<unsigned>>(insertStructs(usedGlobals.resources)) : insertStructs(*it->value, usedGlobals.resources);
    if (!maybeGroups) {
        insertDynamicOffsetsBufferIfNeeded(entryPoint.function);
        return maybeGroups.error();
    }
    insertParameters(entryPoint.function, *maybeGroups);
    insertMaterializations(entryPoint.function, usedGlobals.resources);
    insertLocalDefinitions(entryPoint.function, usedGlobals.privateGlobals);

    for (auto* global : usedGlobals.privateGlobals) {
        if (!global || !global->declaration)
            continue;
        auto* variable = global->declaration;
        if (variable->addressSpace() == AddressSpace::Workgroup)
            m_entryPointInformation->sizeForWorkgroupVariables += getRoundedSize(*variable);
    }
    return std::nullopt;
}

void RewriteGlobalVariables::collectDynamicOffsetGlobals(const PipelineLayout& pipelineLayout)
{
    unsigned group = 0;
    for (const auto& bindGroupLayout : pipelineLayout.bindGroupLayouts) {
        for (const auto& entry : bindGroupLayout.entries) {
            if (!entry.visibility.contains(m_stage))
                continue;

            auto bufferDynamicOffset = [&] {
                switch (m_stage) {
                case ShaderStage::Vertex:
                    return entry.vertexBufferDynamicOffset;
                case ShaderStage::Fragment:
                    return entry.fragmentBufferDynamicOffset;
                case ShaderStage::Compute:
                    return entry.computeBufferDynamicOffset;
                }
            }();

            if (!bufferDynamicOffset.has_value())
                continue;

            m_globalsUsingDynamicOffset.add({ group + 1, entry.binding + 1 }, *bufferDynamicOffset);
        }
        ++group;
    }
}

static WGSL::StorageTextureAccess convertAccess(const AccessMode accessMode)
{
    switch (accessMode) {
    case AccessMode::Read:
        return WGSL::StorageTextureAccess::ReadOnly;
    case AccessMode::ReadWrite:
        return WGSL::StorageTextureAccess::ReadWrite;
    case AccessMode::Write:
        return WGSL::StorageTextureAccess::WriteOnly;
    }
}

static BindGroupLayoutEntry::BindingMember bindingMemberForGlobal(auto& global)
{
    auto* variable = global.declaration;
    ASSERT(variable);
    auto* maybeReference = variable->maybeReferenceType();
    auto* type = variable->storeType();
    ASSERT(type);
    auto addressSpace = [&]() {
        if (maybeReference) {
            auto& reference = downcast<AST::ReferenceTypeExpression>(*maybeReference);
            auto* referenceType = std::get_if<Types::Reference>(reference.inferredType());
            if (referenceType && referenceType->addressSpace == AddressSpace::Storage)
                return referenceType->accessMode == AccessMode::Read ? BufferBindingType::ReadOnlyStorage : BufferBindingType::Storage;
        }

        return BufferBindingType::Uniform;
    };

    using namespace WGSL::Types;
    return WTF::switchOn(*type, [&](const Primitive& primitive) -> BindGroupLayoutEntry::BindingMember {
        switch (primitive.kind) {
        case Types::Primitive::AbstractInt:
        case Types::Primitive::I32:
        case Types::Primitive::U32:
        case Types::Primitive::AbstractFloat:
        case Types::Primitive::F32:
        case Types::Primitive::F16:
        case Types::Primitive::Void:
        case Types::Primitive::Bool:
            return BufferBindingLayout {
                .type = addressSpace(),
                .hasDynamicOffset = false,
                .minBindingSize = type->size()
            };
        case Types::Primitive::Sampler:
            return SamplerBindingLayout {
                .type = SamplerBindingType::Filtering
            };
        case Types::Primitive::SamplerComparison:
            return SamplerBindingLayout {
                .type = SamplerBindingType::Comparison
            };
        case Types::Primitive::TextureExternal:
            return ExternalTextureBindingLayout { };
        case Types::Primitive::AccessMode:
        case Types::Primitive::TexelFormat:
        case Types::Primitive::AddressSpace:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }, [&](const Vector& vector) -> BindGroupLayoutEntry::BindingMember {
        auto* primitive = std::get_if<Primitive>(vector.element);
        UNUSED_PARAM(primitive);
        return BufferBindingLayout {
            .type = addressSpace(),
            .hasDynamicOffset = false,
            .minBindingSize = type->size()
        };
    }, [&](const Matrix& matrix) -> BindGroupLayoutEntry::BindingMember {
        UNUSED_PARAM(matrix);
        return BufferBindingLayout {
            .type = addressSpace(),
            .hasDynamicOffset = false,
            .minBindingSize = type->size()
        };
    }, [&](const Array& array) -> BindGroupLayoutEntry::BindingMember {
        UNUSED_PARAM(array);
        return BufferBindingLayout {
            .type = addressSpace(),
            .hasDynamicOffset = false,
            .minBindingSize = type->size()
        };
    }, [&](const Struct& structure) -> BindGroupLayoutEntry::BindingMember {
        UNUSED_PARAM(structure);
        return BufferBindingLayout {
            .type = addressSpace(),
            .hasDynamicOffset = false,
            .minBindingSize = type->size()
        };
    }, [&](const Texture& texture) -> BindGroupLayoutEntry::BindingMember {
        TextureViewDimension viewDimension;
        bool multisampled = false;
        switch (texture.kind) {
        case Types::Texture::Kind::Texture1d:
            viewDimension = TextureViewDimension::OneDimensional;
            break;
        case Types::Texture::Kind::Texture2d:
            viewDimension = TextureViewDimension::TwoDimensional;
            break;
        case Types::Texture::Kind::Texture2dArray:
            viewDimension = TextureViewDimension::TwoDimensionalArray;
            break;
        case Types::Texture::Kind::Texture3d:
            viewDimension = TextureViewDimension::ThreeDimensional;
            break;
        case Types::Texture::Kind::TextureCube:
            viewDimension = TextureViewDimension::Cube;
            break;
        case Types::Texture::Kind::TextureCubeArray:
            viewDimension = TextureViewDimension::CubeArray;
            break;
        case Types::Texture::Kind::TextureMultisampled2d:
            viewDimension = TextureViewDimension::TwoDimensional;
            multisampled = true;
            break;
        }

        return TextureBindingLayout {
            .sampleType = TextureSampleType::UnfilterableFloat,
            .viewDimension = viewDimension,
            .multisampled = multisampled
        };
    }, [&](const TextureStorage& texture) -> BindGroupLayoutEntry::BindingMember {
        TextureViewDimension viewDimension;
        switch (texture.kind) {
        case Types::TextureStorage::Kind::TextureStorage1d:
            viewDimension = TextureViewDimension::OneDimensional;
            break;
        case Types::TextureStorage::Kind::TextureStorage2d:
            viewDimension = TextureViewDimension::TwoDimensional;
            break;
        case Types::TextureStorage::Kind::TextureStorage2dArray:
            viewDimension = TextureViewDimension::TwoDimensionalArray;
            break;
        case Types::TextureStorage::Kind::TextureStorage3d:
            viewDimension = TextureViewDimension::ThreeDimensional;
            break;
        }

        return StorageTextureBindingLayout {
            .access = convertAccess(texture.access),
            .format = texture.format,
            .viewDimension = viewDimension
        };
    }, [&](const TextureDepth& texture) -> BindGroupLayoutEntry::BindingMember {
        TextureViewDimension viewDimension;
        bool multisampled = false;
        switch (texture.kind) {
        case Types::TextureDepth::Kind::TextureDepth2d:
            viewDimension = TextureViewDimension::TwoDimensional;
            break;
        case Types::TextureDepth::Kind::TextureDepth2dArray:
            viewDimension = TextureViewDimension::TwoDimensionalArray;
            break;
        case Types::TextureDepth::Kind::TextureDepthCube:
            viewDimension = TextureViewDimension::Cube;
            break;
        case Types::TextureDepth::Kind::TextureDepthCubeArray:
            viewDimension = TextureViewDimension::CubeArray;
            break;
        case Types::TextureDepth::Kind::TextureDepthMultisampled2d:
            viewDimension = TextureViewDimension::TwoDimensional;
            multisampled = true;
            break;
        }

        return TextureBindingLayout {
            .sampleType = TextureSampleType::Depth,
            .viewDimension = viewDimension,
            .multisampled = multisampled
        };
    }, [&](const Atomic&) -> BindGroupLayoutEntry::BindingMember {
        return BufferBindingLayout {
            .type = addressSpace(),
            .hasDynamicOffset = false,
            .minBindingSize = type->size()
        };
    }, [&](const PrimitiveStruct&) -> BindGroupLayoutEntry::BindingMember {
        RELEASE_ASSERT_NOT_REACHED();
    }, [&](const Reference&) -> BindGroupLayoutEntry::BindingMember {
        RELEASE_ASSERT_NOT_REACHED();
    }, [&](const Pointer&) -> BindGroupLayoutEntry::BindingMember {
        RELEASE_ASSERT_NOT_REACHED();
    }, [&](const Function&) -> BindGroupLayoutEntry::BindingMember {
        RELEASE_ASSERT_NOT_REACHED();
    }, [&](const TypeConstructor&) -> BindGroupLayoutEntry::BindingMember {
        RELEASE_ASSERT_NOT_REACHED();
    });
}

auto RewriteGlobalVariables::determineUsedGlobals(const AST::Function& function) -> Result<UsedGlobals>
{
    UsedGlobals usedGlobals;

    // https://www.w3.org/TR/WGSL/#limits
    constexpr unsigned maximumCombinedPrivateVariablesSize = 8192;
    unsigned maximumCombinedWorkgroupVariablesSize = m_shaderModule.configuration().maximumCombinedWorkgroupVariablesSize;
    Vector<const Type*, 16> workgroupVariables;
    Vector<const Type*, 16> privateVariables;

    for (const auto& globalName : m_reads) {
        auto it = m_globals.find(globalName);
        RELEASE_ASSERT(it != m_globals.end());
        auto& global = it->value;
        AST::Variable& variable = *global.declaration;
        switch (variable.flavor()) {
        case AST::VariableFlavor::Override:
            usesOverride(variable);
            continue;
        case AST::VariableFlavor::Var:
        case AST::VariableFlavor::Let:
        case AST::VariableFlavor::Const:
            if (!global.resource.has_value()) {
                usedGlobals.privateGlobals.append(&global);

                if (auto* qualifier = variable.maybeQualifier(); qualifier && qualifier->addressSpace() == AddressSpace::Workgroup)
                    workgroupVariables.append(variable.storeType());
                else
                    privateVariables.append(variable.storeType());
                continue;
            }
            break;
        }

        auto group = global.resource->group;
        auto binding = global.resource->binding;
        auto groupResult = usedGlobals.resources.add(group, IndexMap<Global*>());
        auto bindingResult = groupResult.iterator->value.add(binding, &global);

        // FIXME: <rdar://150368198> this check needs to occur during WGSL::staticCheck
        if (!bindingResult.isNewEntry)
            return makeUnexpected(Error(makeString("entry point '"_s, m_entryPointInformation->originalName, "' uses variables '"_s, bindingResult.iterator->value->declaration->originalName(), "' and '"_s, variable.originalName(), "', both which use the same resource binding: @group("_s, group, ") @binding("_s, binding, ')'), variable.span()));
    }

    m_shaderModule.addOverrideValidation([span = function.span(), variables = WTFMove(workgroupVariables), maximumCombinedWorkgroupVariablesSize] -> std::optional<Error> {
        CheckedUint32 combinedWorkgroupVariablesSize = 0;
        for (const Type* type : variables)
            combinedWorkgroupVariablesSize += type->size();
        if (combinedWorkgroupVariablesSize.hasOverflowed() || combinedWorkgroupVariablesSize.value() > maximumCombinedWorkgroupVariablesSize) [[unlikely]]
            return { Error(makeString("The combined byte size of all variables in the workgroup address space exceeds "_s, String::number(maximumCombinedWorkgroupVariablesSize), " bytes"_s), span) };
        return std::nullopt;
    });
    m_shaderModule.addOverrideValidation([span = function.span(), variables = WTFMove(privateVariables)] -> std::optional<Error> {
        CheckedUint32 combinedPrivateVariablesSize = 0;
        for (const Type* type : variables)
            combinedPrivateVariablesSize += type->size();
        if (combinedPrivateVariablesSize.hasOverflowed() || combinedPrivateVariablesSize.value() > maximumCombinedPrivateVariablesSize) [[unlikely]]
            return { Error(makeString("The combined byte size of all variables in the private address space exceeds "_s, String::number(maximumCombinedPrivateVariablesSize), " bytes"_s), span) };
        return std::nullopt;
    });


    return usedGlobals;
}

void RewriteGlobalVariables::usesOverride(AST::Variable& variable)
{
    Reflection::SpecializationConstantType constantType;
    const Type* type = variable.storeType();
    ASSERT(std::holds_alternative<Types::Primitive>(*type));
    const auto& primitive = std::get<Types::Primitive>(*type);
    switch (primitive.kind) {
    case Types::Primitive::Bool:
        constantType = Reflection::SpecializationConstantType::Boolean;
        break;
    case Types::Primitive::F32:
        constantType = Reflection::SpecializationConstantType::Float;
        break;
    case Types::Primitive::F16:
        constantType = Reflection::SpecializationConstantType::Half;
        break;
    case Types::Primitive::I32:
        constantType = Reflection::SpecializationConstantType::Int;
        break;
    case Types::Primitive::U32:
        constantType = Reflection::SpecializationConstantType::Unsigned;
        break;
    case Types::Primitive::Void:
    case Types::Primitive::AbstractInt:
    case Types::Primitive::AbstractFloat:
    case Types::Primitive::Sampler:
    case Types::Primitive::SamplerComparison:
    case Types::Primitive::TextureExternal:
    case Types::Primitive::AccessMode:
    case Types::Primitive::TexelFormat:
    case Types::Primitive::AddressSpace:
        RELEASE_ASSERT_NOT_REACHED();
    }

    String entryName = variable.originalName();
    if (variable.id())
        entryName = String::number(*variable.id());
    m_entryPointInformation->specializationConstants.add(entryName, Reflection::SpecializationConstant { variable.name(), constantType, variable.maybeInitializer() });
}

enum class BindingType {
    Undefined,
    Buffer,
    Texture,
    TextureMultisampled,
    TextureStorageReadOnly,
    TextureStorageReadWrite,
    TextureStorageWriteOnly,
    Sampler,
    SamplerComparison,
    TextureExternal,
};

static BindingType bindingTypeForPrimitive(const Types::Primitive& primitive)
{
    switch (primitive.kind) {
    case Types::Primitive::AbstractInt:
    case Types::Primitive::AbstractFloat:
    case Types::Primitive::I32:
    case Types::Primitive::U32:
    case Types::Primitive::F32:
    case Types::Primitive::F16:
    case Types::Primitive::Bool:
    case Types::Primitive::Void:
        return BindingType::Buffer;
    case Types::Primitive::Sampler:
        return BindingType::Sampler;
    case Types::Primitive::SamplerComparison:
        return BindingType::SamplerComparison;

    case Types::Primitive::TextureExternal:
        return BindingType::TextureExternal;

    case Types::Primitive::AccessMode:
    case Types::Primitive::TexelFormat:
    case Types::Primitive::AddressSpace:
        return BindingType::Undefined;
    }
}

static BindingType bindingTypeForType(const Type* type)
{
    if (!type)
        return BindingType::Undefined;

    return WTF::switchOn(*type,
        [&](const Types::Primitive& primitive) {
            return bindingTypeForPrimitive(primitive);
        },
        [&](const Types::Vector&) {
            return BindingType::Buffer;
        },
        [&](const Types::Array&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::Struct&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::PrimitiveStruct&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::Matrix&) {
            return BindingType::Buffer;
        },
        [&](const Types::Reference&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::Pointer&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::Function&) -> BindingType {
            RELEASE_ASSERT_NOT_REACHED();
        },
        [&](const Types::Texture& texture) {
        return texture.kind == Types::Texture::Kind::TextureMultisampled2d ? BindingType::TextureMultisampled : BindingType::Texture;
        },
        [&](const Types::TextureStorage& storageTexture) {
        switch (storageTexture.access) {
        case AccessMode::Read:
            return BindingType::TextureStorageReadOnly;
        case AccessMode::ReadWrite:
            return BindingType::TextureStorageReadWrite;
        case AccessMode::Write:
            return BindingType::TextureStorageWriteOnly;
        }
        },
        [&](const Types::TextureDepth& texture) {
            return texture.kind == Types::TextureDepth::Kind::TextureDepthMultisampled2d ? BindingType::TextureMultisampled : BindingType::Texture;
        },
        [&](const Types::Atomic&) -> BindingType {
            return BindingType::Buffer;
        },
        [&](const Types::TypeConstructor&) -> BindingType {
            RELEASE_ASSERT_NOT_REACHED();
        });
}

static bool isExternalTexture(const AST::Variable& variable)
{
    return bindingTypeForType(variable.storeType()) == BindingType::TextureExternal;
}

Vector<unsigned> RewriteGlobalVariables::insertStructs(const UsedResources& usedResources)
{
    Vector<unsigned> groups;
    for (auto& groupBinding : m_groupBindingMap) {
        auto usedResource = usedResources.find(groupBinding.key);
        if (usedResource == usedResources.end())
            continue;

        auto& bindingGlobalMap = groupBinding.value;
        const IndexMap<Global*>& usedBindings = usedResource->value;

        Vector<std::pair<unsigned, AST::StructureMember*>> entries;
        unsigned metalId = 0;
        HashMap<AST::Variable*, unsigned> bufferSizeToOwnerMap;
        for (auto [binding, globalName] : bindingGlobalMap) {
            unsigned group = groupBinding.key;
            auto it = m_globals.find(globalName);
            RELEASE_ASSERT(it != m_globals.end());
            auto& global = it->value;

            if (auto bufferIt = m_reverseBufferLengthMap.find(global.declaration); bufferIt != m_reverseBufferLengthMap.end()) {
                if (isExternalTexture(*bufferIt->value))
                    continue;
                if (bufferIt->value->addressSpace() != AddressSpace::Storage)
                    continue;
                if (!bufferSizeToOwnerMap.contains(global.declaration))
                    continue;
            } else if (!usedBindings.contains(binding))
                continue;
            else if (!m_reads.contains(globalName))
                continue;
            ASSERT(global.declaration->maybeTypeName());

            entries.append({ metalId, &createArgumentBufferEntry(metalId, *global.declaration) });

            if (auto it = m_generateLayoutGroupMapping.find(groupBinding.key); it != m_generateLayoutGroupMapping.end())
                group = it->value;
            else {
                auto newGroup = m_generatedLayout->bindGroupLayouts.size();
                m_generateLayoutGroupMapping.add(group, newGroup);
                m_generatedLayout->bindGroupLayouts.append({ group, { } });
                group = newGroup;
            }

            BindGroupLayoutEntry entry {
                .binding = metalId,
                .webBinding = global.resource->binding,
                .visibility = m_stage,
                .bindingMember = bindingMemberForGlobal(global),
                .name = global.declaration->name(),
                .vertexArgumentBufferIndex = std::nullopt,
                .vertexArgumentBufferSizeIndex = std::nullopt,
                .vertexBufferDynamicOffset = std::nullopt,
                .fragmentArgumentBufferIndex = std::nullopt,
                .fragmentArgumentBufferSizeIndex = std::nullopt,
                .fragmentBufferDynamicOffset = std::nullopt,
                .computeArgumentBufferIndex = std::nullopt,
                .computeArgumentBufferSizeIndex = std::nullopt,
                .computeBufferDynamicOffset = std::nullopt
            };

            auto bufferSizeIt = m_bufferLengthMap.find(global.declaration);
            if (bufferSizeIt != m_bufferLengthMap.end()) {
                auto* variable = bufferSizeIt->value;
                bufferSizeToOwnerMap.add(variable, m_generatedLayout->bindGroupLayouts[group].entries.size());
            } else if (auto ownerIt = bufferSizeToOwnerMap.find(global.declaration); ownerIt != bufferSizeToOwnerMap.end()) {
                // FIXME: <rdar://150369108> since we only ever generate a layout
                // for one shader stage at a time, we always store the indices in
                // the vertex slot, but we should use a structs to pass information
                // from the compiler to the API (instead of reusing the same struct
                // the API uses to pass information to the compiler)
                m_generatedLayout->bindGroupLayouts[group].entries[ownerIt->value].vertexArgumentBufferSizeIndex = metalId;
            }

            auto* type = global.declaration->storeType();
            if (isPrimitive(type, Types::Primitive::TextureExternal))
                metalId += 4;
            else
                ++metalId;

            m_generatedLayout->bindGroupLayouts[group].entries.append(WTFMove(entry));
        }

        if (entries.isEmpty())
            continue;

        groups.append(groupBinding.key);
        finalizeArgumentBufferStruct(groupBinding.key, entries);
    }
    return groups;
}

AST::StructureMember& RewriteGlobalVariables::createArgumentBufferEntry(unsigned binding, AST::Variable& variable)
{
    return createArgumentBufferEntry(binding, variable.span(), variable.name(), *variable.maybeReferenceType());
}


AST::StructureMember& RewriteGlobalVariables::createArgumentBufferEntry(unsigned binding, const SourceSpan& span, const String& name, AST::Expression& type)
{
    auto& bindingValue = m_shaderModule.astBuilder().construct<AST::AbstractIntegerLiteral>(span, binding);
    bindingValue.m_inferredType = m_shaderModule.types().abstractIntType();
    bindingValue.setConstantValue(binding);
    auto& bindingAttribute = m_shaderModule.astBuilder().construct<AST::BindingAttribute>(span, bindingValue);
    ++m_entryPointInformation->bindingCount;
    return m_shaderModule.astBuilder().construct<AST::StructureMember>(
        span,
        AST::Identifier::make(name),
        type,
        AST::Attribute::List { bindingAttribute }
    );
}

void RewriteGlobalVariables::finalizeArgumentBufferStruct(unsigned group, Vector<std::pair<unsigned, AST::StructureMember*>>& entries)
{
    std::ranges::sort(entries, { }, &std::pair<unsigned, AST::StructureMember*>::first);

    AST::StructureMember::List structMembers;
    for (auto& [_, member] : entries)
        structMembers.append(*member);

    auto& argumentBufferStruct = m_shaderModule.astBuilder().construct<AST::Structure>(
        SourceSpan::empty(),
        argumentBufferStructName(group),
        WTFMove(structMembers),
        AST::Attribute::List { },
        AST::StructureRole::BindGroup
    );
    argumentBufferStruct.m_inferredType = m_shaderModule.types().structType(argumentBufferStruct);
    m_shaderModule.append(m_shaderModule.declarations(), argumentBufferStruct);
    m_structTypes.add(group, argumentBufferStruct.m_inferredType);
}

static AddressSpace addressSpaceForBindingMember(const BindGroupLayoutEntry::BindingMember& bindingMember)
{
    return WTF::switchOn(bindingMember, [](const BufferBindingLayout& bufferBinding) {
        switch (bufferBinding.type) {
        case BufferBindingType::Uniform:
            return AddressSpace::Uniform;
        case BufferBindingType::Storage:
            return AddressSpace::Storage;
        case BufferBindingType::ReadOnlyStorage:
            return AddressSpace::Storage;
        }
    }, [](const SamplerBindingLayout&) {
        return AddressSpace::Handle;
    }, [](const TextureBindingLayout&) {
        return AddressSpace::Handle;
    }, [](const StorageTextureBindingLayout&) {
        return AddressSpace::Handle;
    }, [](const ExternalTextureBindingLayout&) {
        return AddressSpace::Handle;
    });
}

static AccessMode accessModeForBindingMember(const BindGroupLayoutEntry::BindingMember& bindingMember)
{
    return WTF::switchOn(bindingMember, [](const BufferBindingLayout& bufferBinding) {
        switch (bufferBinding.type) {
        case BufferBindingType::Uniform:
            return AccessMode::Read;
        case BufferBindingType::Storage:
            return AccessMode::ReadWrite;
        case BufferBindingType::ReadOnlyStorage:
            return AccessMode::Read;
        }
    }, [](const SamplerBindingLayout&) {
        return AccessMode::Read;
    }, [](const TextureBindingLayout&) {
        return AccessMode::Read;
    }, [](const StorageTextureBindingLayout&) {
        return AccessMode::Read;
    }, [](const ExternalTextureBindingLayout&) {
        return AccessMode::Read;
    });
}

static bool isBuffer(const AST::Variable& variable)
{
    return bindingTypeForType(variable.storeType()) == BindingType::Buffer;
}

static bool isSampler(const AST::Variable& variable, SamplerBindingType bindingType)
{
    switch (bindingType) {
    case SamplerBindingType::Filtering:
    case SamplerBindingType::NonFiltering:
        return bindingTypeForType(variable.storeType()) == BindingType::Sampler;
    case SamplerBindingType::Comparison:
        return bindingTypeForType(variable.storeType()) == BindingType::SamplerComparison;
    }
}

static bool textureKindEqualsViewDimension(Types::Texture::Kind kind, TextureViewDimension viewDimension, bool isMultisampled, TextureSampleType sampleType)
{
    if (isMultisampled)
        return kind == Types::Texture::Kind::TextureMultisampled2d && viewDimension == TextureViewDimension::TwoDimensional;

    switch (viewDimension) {
    case TextureViewDimension::OneDimensional:
        return kind == Types::Texture::Kind::Texture1d && sampleType != TextureSampleType::Depth;
    case TextureViewDimension::TwoDimensional:
        return kind == Types::Texture::Kind::Texture2d;
    case TextureViewDimension::TwoDimensionalArray:
        return kind == Types::Texture::Kind::Texture2dArray;
    case TextureViewDimension::Cube:
        return kind == Types::Texture::Kind::TextureCube;
    case TextureViewDimension::CubeArray:
        return kind == Types::Texture::Kind::TextureCubeArray;
    case TextureViewDimension::ThreeDimensional:
        return kind == Types::Texture::Kind::Texture3d && sampleType != TextureSampleType::Depth;
    }

    return false;
}

static bool depthTextureKindEqualsViewDimension(Types::TextureDepth::Kind kind, TextureViewDimension viewDimension, bool isMultisampled)
{
    if (isMultisampled)
        return kind == Types::TextureDepth::Kind::TextureDepthMultisampled2d && viewDimension == TextureViewDimension::TwoDimensional;

    switch (viewDimension) {
    case TextureViewDimension::OneDimensional:
        return false;
    case TextureViewDimension::TwoDimensional:
        return kind == Types::TextureDepth::Kind::TextureDepth2d;
    case TextureViewDimension::TwoDimensionalArray:
        return kind == Types::TextureDepth::Kind::TextureDepth2dArray;
    case TextureViewDimension::Cube:
        return kind == Types::TextureDepth::Kind::TextureDepthCube;
    case TextureViewDimension::CubeArray:
        return kind == Types::TextureDepth::Kind::TextureDepthCubeArray;
    case TextureViewDimension::ThreeDimensional:
        return false;
    }

    return false;
}

static ASCIILiteral nameForBindingType(BindingType bindingType)
{
    switch (bindingType) {
    default:
    case BindingType::Undefined:
        return "Undefined"_s;
    case BindingType::Buffer:
        return "Buffer"_s;
    case BindingType::Texture:
        return "Texture"_s;
    case BindingType::TextureMultisampled:
        return "TextureMultisampled"_s;
    case BindingType::TextureStorageReadOnly:
        return "TextureStorageReadOnly"_s;
    case BindingType::TextureStorageReadWrite:
        return "TextureStorageReadWrite"_s;
    case BindingType::TextureStorageWriteOnly:
        return "TextureStorageWriteOnly"_s;
    case BindingType::Sampler:
        return "Sampler"_s;
    case BindingType::SamplerComparison:
        return "SamplerComparison"_s;
    case BindingType::TextureExternal:
        return "TextureExternal"_s;
    }
}

static ASCIILiteral nameForTextureSampleType(TextureSampleType sampleType)
{
    switch (sampleType) {
    case TextureSampleType::Float:
        return "Float"_s;
    case TextureSampleType::UnfilterableFloat:
        return "UnfilterableFloat"_s;
    case TextureSampleType::Depth:
        return "Depth"_s;
    case TextureSampleType::SignedInt:
        return "SignedInt"_s;
    case TextureSampleType::UnsignedInt:
        return "UnsignedInt"_s;
    default:
        return "Undefined"_s;
    }
}

static ASCIILiteral nameForTextureDepthKind(Types::TextureDepth::Kind kind)
{
    switch (kind) {
    case Types::TextureDepth::Kind::TextureDepth2d:
        return "TextureDepth2d"_s;
    case Types::TextureDepth::Kind::TextureDepth2dArray:
        return "TextureDepth2d"_s;
    case Types::TextureDepth::Kind::TextureDepthCube:
        return "TextureDepth2d"_s;
    case Types::TextureDepth::Kind::TextureDepthCubeArray:
        return "TextureDepth2d"_s;
    case Types::TextureDepth::Kind::TextureDepthMultisampled2d:
        return "Texture2d"_s;
    default:
        return "Undefined"_s;
    }
}

static ASCIILiteral nameForTextureKind(Types::Texture::Kind kind)
{
    switch (kind) {
    case Types::Texture::Kind::Texture1d:
        return "Texture1d"_s;
    case Types::Texture::Kind::Texture2d:
        return "Texture2d"_s;
    case Types::Texture::Kind::Texture2dArray:
        return "Texture2d"_s;
    case Types::Texture::Kind::TextureCube:
        return "Texture2d"_s;
    case Types::Texture::Kind::TextureCubeArray:
        return "Texture2d"_s;
    case Types::Texture::Kind::TextureMultisampled2d:
        return "Texture2d"_s;
    case Types::Texture::Kind::Texture3d:
        return "Texture3d"_s;
    default:
        return "Undefined"_s;
    }
}

static ASCIILiteral nameForTextureViewDimension(TextureViewDimension viewDimension)
{
    switch (viewDimension) {
    case TextureViewDimension::OneDimensional:
        return "1d"_s;
    case TextureViewDimension::TwoDimensional:
        return "2d"_s;
    case TextureViewDimension::TwoDimensionalArray:
        return "2d_array"_s;
    case TextureViewDimension::Cube:
        return "cube"_s;
    case TextureViewDimension::CubeArray:
        return "cube-array"_s;
    case TextureViewDimension::ThreeDimensional:
        return "3d"_s;
    }

    return "undefined"_s;
}

static ASCIILiteral nameForPrimitiveKind(Types::Primitive::Kind primitiveKind)
{
    switch (primitiveKind) {
    case Types::Primitive::AbstractInt:
        return "<AbstractInt>"_s;
    case Types::Primitive::I32:
        return "int32"_s;
    case Types::Primitive::U32:
        return "uint32"_s;
    case Types::Primitive::AbstractFloat:
        return "<AbstractFloat>"_s;
    case Types::Primitive::F16:
        return "f16"_s;
    case Types::Primitive::F32:
        return "f32"_s;
    case Types::Primitive::Void:
        return "void"_s;
    case Types::Primitive::Bool:
        return "bool"_s;
    case Types::Primitive::Sampler:
        return "sampler"_s;
    case Types::Primitive::SamplerComparison:
        return "sampler_comparion"_s;
    case Types::Primitive::TextureExternal:
        return "texture_external"_s;
    case Types::Primitive::AccessMode:
        return "access_mode"_s;
    case Types::Primitive::TexelFormat:
        return "texel_format"_s;
    case Types::Primitive::AddressSpace:
        return "address_space"_s;
    }

    return "undefined"_s;
}

static String errorValidatingTexture(const AST::Variable& variable, const TextureBindingLayout& textureBinding)
{
    bool isMultisampled = textureBinding.multisampled;
    auto targetValue = isMultisampled ? BindingType::TextureMultisampled : BindingType::Texture;
    auto storeType = variable.storeType();
    auto bindingForType = bindingTypeForType(storeType);
    if (bindingForType != targetValue)
        return makeString("types don't match: WGSL type "_s, nameForBindingType(bindingForType), " target type "_s, nameForBindingType(targetValue));

    auto sampleType = textureBinding.sampleType;
    const Types::Texture* possibleTexture = std::get_if<Types::Texture>(storeType);
    if (!possibleTexture) {
        const Types::TextureDepth* possibleTextureDepth = std::get_if<Types::TextureDepth>(storeType);
        if (!possibleTextureDepth || sampleType != TextureSampleType::Depth)
            return makeString("depth validation failed: "_s, nameForTextureSampleType(sampleType));

        bool result = depthTextureKindEqualsViewDimension(possibleTextureDepth->kind, textureBinding.viewDimension, isMultisampled);
        if (!result)
            return makeString("viewDimensions don't match: "_s, nameForTextureDepthKind(possibleTextureDepth->kind), ", textureBinding view dimension "_s, nameForTextureViewDimension(textureBinding.viewDimension), ", multisampled = "_s, isMultisampled ? "yes"_s : "no"_s);

        return emptyString();
    }

    if (!textureKindEqualsViewDimension(possibleTexture->kind, textureBinding.viewDimension, isMultisampled, sampleType) || !possibleTexture->element)
        return makeString("viewDimensions don't match: "_s, nameForTextureKind(possibleTexture->kind), ", bindingViewDimension = "_s, nameForTextureViewDimension(textureBinding.viewDimension), ", multisampled = "_s, isMultisampled ? "yes"_s : "no"_s, ", bindingSampleType = "_s, nameForTextureSampleType(sampleType));

    bool result = false;
    if (const auto* primitive = std::get_if<Types::Primitive>(possibleTexture->element)) {
        switch (sampleType) {
        case TextureSampleType::Float:
        case TextureSampleType::UnfilterableFloat:
            result = primitive->kind == Types::Primitive::F32 || primitive->kind == Types::Primitive::F16;
            break;
        case TextureSampleType::Depth:
            break;
        case TextureSampleType::SignedInt:
            result = primitive->kind == Types::Primitive::I32;
            break;
        case TextureSampleType::UnsignedInt:
            result = primitive->kind == Types::Primitive::U32;
            break;
        }

        if (!result)
            return makeString("element types don't match: sampleType "_s, nameForTextureSampleType(sampleType), ", primitive->kind "_s, nameForPrimitiveKind(primitive->kind));
    }

    if (!result)
        return makeString("WGSL texture has no elementType: sampleType "_s, nameForTextureSampleType(sampleType));

    return emptyString();
}

static bool storageTextureKindEqualsViewDimension(Types::TextureStorage::Kind kind, TextureViewDimension viewDimension)
{
    switch (viewDimension) {
    case TextureViewDimension::OneDimensional:
        return kind == Types::TextureStorage::Kind::TextureStorage1d;
    case TextureViewDimension::TwoDimensional:
        return kind == Types::TextureStorage::Kind::TextureStorage2d;
    case TextureViewDimension::TwoDimensionalArray:
        return kind == Types::TextureStorage::Kind::TextureStorage2dArray;
    case TextureViewDimension::Cube:
        return false;
    case TextureViewDimension::CubeArray:
        return false;
    case TextureViewDimension::ThreeDimensional:
        return kind == Types::TextureStorage::Kind::TextureStorage3d;
    }

    return false;
}

static bool isStorageTexture(const AST::Variable& variable, const StorageTextureBindingLayout& storageTexture)
{
    auto textureAccess = storageTexture.access;
    auto storeType = variable.storeType();
    const Types::TextureStorage* possibleStorageTexture = std::get_if<Types::TextureStorage>(storeType);
    if (!possibleStorageTexture)
        return false;

    if (!storageTextureKindEqualsViewDimension(possibleStorageTexture->kind, storageTexture.viewDimension) || possibleStorageTexture->format != storageTexture.format)
        return false;

    switch (bindingTypeForType(storeType)) {
    case BindingType::TextureStorageReadOnly:
        return textureAccess == StorageTextureAccess::ReadOnly;
    case BindingType::TextureStorageReadWrite:
        return textureAccess == StorageTextureAccess::ReadWrite;
    case BindingType::TextureStorageWriteOnly:
        return textureAccess == StorageTextureAccess::WriteOnly || textureAccess == StorageTextureAccess::ReadWrite;
    default:
        return false;
    }
}

static String errorValidatingTypes(const AST::Variable& variable, const BindGroupLayoutEntry::BindingMember& bindingMember)
{
    return WTF::switchOn(bindingMember, [&](const BufferBindingLayout&) {
        return isBuffer(variable) ? emptyString() : "WGSL variable is not a buffer"_s;
    }, [&](const SamplerBindingLayout& samplerBinding) {
        return isSampler(variable, samplerBinding.type) ? emptyString() : "WGSL variable is not a sampler"_s;
    }, [&](const TextureBindingLayout& textureBinding) {
        return errorValidatingTexture(variable, textureBinding);
    }, [&](const StorageTextureBindingLayout& storageTexture) {
        return isStorageTexture(variable, storageTexture) ? emptyString() : "WGSL variable is not a storage texture"_s;
    }, [&](const ExternalTextureBindingLayout&) {
        return isExternalTexture(variable) ? emptyString() : "WGSL variable is not an external texture"_s;
    });
}

static String errorValidatingVariableAndEntryMatch(const AST::Variable& variable, const BindGroupLayoutEntry& entry)
{
    if (auto error = errorValidatingTypes(variable, entry.bindingMember); error.length())
        return error;

    auto variableAddressSpace = variable.addressSpace();
    auto entryAddressSpace = addressSpaceForBindingMember(entry.bindingMember);
    if (variableAddressSpace && *variableAddressSpace != entryAddressSpace)
        return "variableAddressSpace != entryAddressSpace"_s;

    auto variableAccessMode = variable.accessMode();
    auto entryAccessMode = accessModeForBindingMember(entry.bindingMember);
    if (variableAccessMode && *variableAccessMode != entryAccessMode)
        return "variableAccessMode != entryAccessMode"_s;

    return emptyString();
}

Result<Vector<unsigned>> RewriteGlobalVariables::insertStructs(PipelineLayout& layout, const UsedResources& usedResources)
{
    Vector<unsigned> groups;
    unsigned group = 0;
    HashMap<AST::Variable*, BindGroupLayoutEntry*> serializedVariables;
    for (auto& bindGroupLayout : layout.bindGroupLayouts) {
        Vector<std::pair<unsigned, AST::StructureMember*>> entries;
        Vector<std::pair<unsigned, AST::Variable*>> bufferLengths;
        for (auto& entry : bindGroupLayout.entries) {
            if (!entry.visibility.contains(m_stage))
                continue;

            auto argumentBufferIndex = [&] {
                switch (m_stage) {
                case ShaderStage::Vertex:
                    return entry.vertexArgumentBufferIndex;
                case ShaderStage::Fragment:
                    return entry.fragmentArgumentBufferIndex;
                case ShaderStage::Compute:
                    return entry.computeArgumentBufferIndex;
                }
            }();
            auto argumentBufferSizeIndex = [&] {
                switch (m_stage) {
                case ShaderStage::Vertex:
                    return entry.vertexArgumentBufferSizeIndex;
                case ShaderStage::Fragment:
                    return entry.fragmentArgumentBufferSizeIndex;
                case ShaderStage::Compute:
                    return entry.computeArgumentBufferSizeIndex;
                }
            }();

            AST::Variable* variable = nullptr;

            auto globalIt = m_globalsByBinding.find({ group + 1, entry.binding + 1 });
            if (globalIt != m_globalsByBinding.end()) {
                auto groupIt = usedResources.find(group);
                if (groupIt != usedResources.end()) {
                    auto& bindings = groupIt->value;
                    auto bindingIt = bindings.find(entry.binding);
                    if (bindingIt != bindings.end()) {
                        variable = bindingIt->value->declaration;
                        serializedVariables.add(variable, &entry);
                        entries.append({ *argumentBufferIndex, &createArgumentBufferEntry(*argumentBufferIndex, *variable) });
                    }
                }
            }

            if (!variable) {
                auto& type = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("void"_s));
                type.m_inferredType = WTF::switchOn(entry.bindingMember,
                    [&](const BufferBindingLayout& buffer) -> const Type* {
                        AddressSpace addressSpace;
                        AccessMode accessMode;
                        switch (buffer.type) {
                        case BufferBindingType::Uniform:
                            addressSpace = AddressSpace::Uniform;
                            accessMode = AccessMode::Read;
                            break;
                        case BufferBindingType::Storage:
                            addressSpace = AddressSpace::Storage;
                            accessMode = AccessMode::ReadWrite;
                            break;
                        case BufferBindingType::ReadOnlyStorage:
                            addressSpace = AddressSpace::Storage;
                            accessMode = AccessMode::Read;
                            break;
                        }
                        return m_shaderModule.types().pointerType(addressSpace, m_shaderModule.types().voidType(), accessMode);
                    },
                    [&](const SamplerBindingLayout&) -> const Type* {
                        return m_shaderModule.types().samplerType();
                    },
                    [&](const TextureBindingLayout& layout) -> const Type* {
                        const Type* sampleType;
                        switch (layout.sampleType) {
                        case TextureSampleType::Float:
                        case TextureSampleType::UnfilterableFloat:
                        case TextureSampleType::Depth:
                            sampleType = m_shaderModule.types().f32Type();
                            break;
                        case TextureSampleType::SignedInt:
                            sampleType = m_shaderModule.types().i32Type();
                            break;
                        case TextureSampleType::UnsignedInt:
                            sampleType = m_shaderModule.types().u32Type();
                            break;
                        }
                        Types::Texture::Kind textureKind;
                        switch (layout.viewDimension) {
                        case TextureViewDimension::OneDimensional:
                            textureKind = Types::Texture::Kind::Texture1d;
                            break;
                        case TextureViewDimension::TwoDimensional:
                            if (layout.multisampled)
                                textureKind = Types::Texture::Kind::TextureMultisampled2d;
                            else
                                textureKind = Types::Texture::Kind::Texture2d;
                            break;
                        case TextureViewDimension::TwoDimensionalArray:
                            textureKind = Types::Texture::Kind::Texture2dArray;
                            break;
                        case TextureViewDimension::Cube:
                            textureKind = Types::Texture::Kind::TextureCube;
                            break;
                        case TextureViewDimension::CubeArray:
                            textureKind = Types::Texture::Kind::TextureCubeArray;
                            break;
                        case TextureViewDimension::ThreeDimensional:
                            textureKind = Types::Texture::Kind::Texture3d;
                            break;
                        }
                        return m_shaderModule.types().textureType(textureKind, sampleType);
                    },
                    [&](const StorageTextureBindingLayout& layout) -> const Type* {
                        Types::TextureStorage::Kind textureStorageKind;
                        switch (layout.viewDimension) {
                        case TextureViewDimension::OneDimensional:
                            textureStorageKind = Types::TextureStorage::Kind::TextureStorage1d;
                            break;
                        case TextureViewDimension::TwoDimensional:
                            textureStorageKind = Types::TextureStorage::Kind::TextureStorage2d;
                            break;
                        case TextureViewDimension::TwoDimensionalArray:
                            textureStorageKind = Types::TextureStorage::Kind::TextureStorage2dArray;
                            break;
                        case TextureViewDimension::ThreeDimensional:
                            textureStorageKind = Types::TextureStorage::Kind::TextureStorage3d;
                            break;
                        default:
                            RELEASE_ASSERT_NOT_REACHED();
                        }
                        AccessMode accessMode;
                        switch (layout.access) {
                        case StorageTextureAccess::WriteOnly:
                            accessMode = AccessMode::Write;
                            break;
                        case StorageTextureAccess::ReadOnly:
                            accessMode = AccessMode::Read;
                            break;
                        case StorageTextureAccess::ReadWrite:
                            accessMode = AccessMode::ReadWrite;
                            break;
                        }
                        return m_shaderModule.types().textureStorageType(textureStorageKind, layout.format, accessMode);
                    },
                    [&](const ExternalTextureBindingLayout&) -> const Type* {
                        m_shaderModule.setUsesExternalTextures();
                        return m_shaderModule.types().textureExternalType();
                    });

                entries.append({
                    *argumentBufferIndex,
                    &createArgumentBufferEntry(*argumentBufferIndex, SourceSpan::empty(), makeString("__ArgumentBufferPlaceholder_"_s, String::number(*argumentBufferIndex)), type)
                });
            }

            if (argumentBufferSizeIndex.has_value())
                bufferLengths.append({ *argumentBufferSizeIndex, variable });
        }

        for (auto [binding, variable] : bufferLengths) {
            if (variable) {
                auto it = m_bufferLengthMap.find(variable);
                RELEASE_ASSERT(it != m_bufferLengthMap.end());
                serializedVariables.add(it->value, nullptr);
                entries.append({ binding, &createArgumentBufferEntry(binding, *it->value) });
            } else {
                entries.append({
                    binding,
                    &createArgumentBufferEntry(binding, SourceSpan::empty(), makeString("__ArgumentBufferPlaceholder_"_s, String::number(binding)), bufferLengthType())
                });
            }
        }

        if (entries.isEmpty()) {
            ++group;
            continue;
        }

        groups.append(group);
        finalizeArgumentBufferStruct(group++, entries);
    }

    for (auto& [_, bindingGlobalMap] : usedResources) {
        for (auto [_, global] : bindingGlobalMap) {
            auto* variable = global->declaration;
            if (auto entryIt = serializedVariables.find(variable); entryIt != serializedVariables.end() && entryIt->value) {
                if (auto error = errorValidatingVariableAndEntryMatch(*variable, *entryIt->value); error.length())
                    return makeUnexpected(Error(makeString("Shader is incompatible with layout pipeline: "_s, error), SourceSpan::empty()));

                if (auto* bufferBindingLayout = std::get_if<BufferBindingLayout>(&entryIt->value->bindingMember))
                    bufferBindingLayout->minBindingSize = variable->storeType()->size();
            }

            if (!m_reads.contains(variable->name()))
                continue;

            if (!serializedVariables.contains(variable))
                return makeUnexpected(Error("Shader is incompatible with layout pipeline"_s, SourceSpan::empty()));
        }
    }

    return { groups };
}

void RewriteGlobalVariables::insertDynamicOffsetsBufferIfNeeded(const SourceSpan& span, const AST::Function& function)
{
    if (!m_globalsUsingDynamicOffset.isEmpty() || (m_stage == ShaderStage::Fragment && (m_shaderModule.usesFragDepth() || m_shaderModule.usesSampleMask()))) {
        unsigned group;
        switch (m_stage) {
        case ShaderStage::Vertex:
            group = m_shaderModule.configuration().maxBuffersPlusVertexBuffersForVertexStage;
            break;
        case ShaderStage::Fragment:
            group = m_shaderModule.configuration().maxBuffersForFragmentStage;
            break;
        case ShaderStage::Compute:
            group = m_shaderModule.configuration().maxBuffersForComputeStage;
            break;
        }

        auto& type = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(span, AST::Identifier::make("u32"_s));
        type.m_inferredType = m_shaderModule.types().pointerType(AddressSpace::Uniform, m_shaderModule.types().u32Type(), AccessMode::Read);

        insertParameter(span, function, group, AST::Identifier::make(dynamicOffsetVariableName()), &type, AST::ParameterRole::UserDefined);
    }
}

void RewriteGlobalVariables::insertDynamicOffsetsBufferIfNeeded(const AST::Function& function)
{
    insertDynamicOffsetsBufferIfNeeded(function.span(), function);
}

void RewriteGlobalVariables::insertParameters(AST::Function& function, const Vector<unsigned>& groups)
{
    auto span = function.span();
    for (auto group : groups)
        insertParameter(span, function, group, argumentBufferParameterName(group));
    insertDynamicOffsetsBufferIfNeeded(span, function);
}

void RewriteGlobalVariables::insertMaterializations(AST::Function& function, const UsedResources& usedResources)
{
    auto span = function.span();
    for (auto& [group, bindings] : usedResources) {
        auto& argument = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
            span,
            AST::Identifier::make(argumentBufferParameterName(group))
        );

        for (auto& [binding, global] : bindings) {
            auto& name = global->declaration->name();
            String fieldName = name;
            auto* storeType = global->declaration->storeType();
            if (isPrimitive(storeType, Types::Primitive::TextureExternal)) {
                fieldName = makeString("__"_s, name);
                m_shaderModule.setUsesExternalTextures();
            }
            auto& access = m_shaderModule.astBuilder().construct<AST::FieldAccessExpression>(
                SourceSpan::empty(),
                argument,
                AST::Identifier::make(WTFMove(fieldName))
            );
            AST::Expression* initializer = &access;

            auto it = global->declaration->binding() ? m_globalsUsingDynamicOffset.find({ group + 1, binding + 1 }) : m_globalsUsingDynamicOffset.end();
            if (it != m_globalsUsingDynamicOffset.end()) {
                auto offset = it->value;
                auto& target = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
                    SourceSpan::empty(),
                    AST::Identifier::make("__dynamicOffset"_s)
                );
                auto& reference = std::get<Types::Reference>(*global->declaration->maybeReferenceType()->inferredType());
                target.m_inferredType = m_shaderModule.types().pointerType(reference.addressSpace, storeType, reference.accessMode);

                auto& offsetExpression = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(span, offset);
                offsetExpression.m_inferredType = m_shaderModule.types().u32Type();
                offsetExpression.setConstantValue(offset);
                initializer = &m_shaderModule.astBuilder().construct<AST::CallExpression>(
                    SourceSpan::empty(),
                    target,
                    AST::Expression::List { access, offsetExpression }
                );
            }

            auto& variable = m_shaderModule.astBuilder().construct<AST::Variable>(
                SourceSpan::empty(),
                AST::VariableFlavor::Let,
                AST::Identifier::make(name),
                nullptr,
                global->declaration->maybeReferenceType(),
                initializer,
                AST::Attribute::List { },
                AST::VariableRole::PackedResource
            );

            auto& variableStatement = m_shaderModule.astBuilder().construct<AST::VariableStatement>(SourceSpan::empty(), variable);
            m_shaderModule.insert(function.body().statements(), 0, std::reference_wrapper<AST::Statement>(variableStatement));
        }
    }
}

void RewriteGlobalVariables::insertLocalDefinitions(AST::Function& function, const UsedPrivateGlobals& usedPrivateGlobals)
{
    auto initialBodySize = function.body().statements().size();
    for (auto* global : usedPrivateGlobals) {
        auto& variableStatement = m_shaderModule.astBuilder().construct<AST::VariableStatement>(SourceSpan::empty(), *global->declaration);
        m_shaderModule.insert(function.body().statements(), 0, std::reference_wrapper<AST::Statement>(variableStatement));
    }

    auto offset = function.body().statements().size() - initialBodySize;
    initializeVariables(function, usedPrivateGlobals, offset);
}

void RewriteGlobalVariables::initializeVariables(AST::Function& function, const UsedPrivateGlobals& globals, size_t offset)
{
    auto initializations = storeInitialValue(globals);
    if (initializations.isEmpty())
        return;

    insertWorkgroupBarrier(function, offset);

    auto localInvocationIndex = findOrInsertLocalInvocationIndex(function);

    auto& testLhs = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
        SourceSpan::empty(),
        AST::Identifier::make(localInvocationIndex.id())
    );
    testLhs.m_inferredType = m_shaderModule.types().u32Type();

    auto& testRhs = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(SourceSpan::empty(), 0);
    testLhs.m_inferredType = m_shaderModule.types().u32Type();


    auto& testExpression = m_shaderModule.astBuilder().construct<AST::BinaryExpression>(
        SourceSpan::empty(),
        testLhs,
        testRhs,
        AST::BinaryOperation::Equal
    );
    testExpression.m_inferredType = m_shaderModule.types().boolType();

    auto& body = m_shaderModule.astBuilder().construct<AST::CompoundStatement>(
        SourceSpan::empty(),
        AST::Attribute::List { },
        WTFMove(initializations)
    );

    auto& ifStatement = m_shaderModule.astBuilder().construct<AST::IfStatement>(
        SourceSpan::empty(),
        testExpression,
        body,
        nullptr,
        AST::Attribute::List { }
    );
    m_shaderModule.insert(function.body().statements(), offset, std::reference_wrapper<AST::Statement>(ifStatement));
}

void RewriteGlobalVariables::insertWorkgroupBarrier(AST::Function& function, size_t offset)
{
    auto& callee = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("workgroupBarrier"_s));
    callee.m_inferredType = m_shaderModule.types().voidType();

    auto& call = m_shaderModule.astBuilder().construct<AST::CallExpression>(
        SourceSpan::empty(),
        callee,
        AST::Expression::List { }
    );
    call.m_inferredType = m_shaderModule.types().voidType();

    auto& callStatement = m_shaderModule.astBuilder().construct<AST::CallStatement>(
        SourceSpan::empty(),
        call
    );
    m_shaderModule.insert(function.body().statements(), offset, std::reference_wrapper<AST::Statement>(callStatement));
}

AST::Identifier& RewriteGlobalVariables::findOrInsertLocalInvocationIndex(AST::Function& function)
{
    for (auto& parameter : function.parameters()) {
        if (auto builtin = parameter.builtin(); builtin.has_value() && *builtin == Builtin::LocalInvocationIndex)
            return parameter.name();
    }

    auto& type = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
        SourceSpan::empty(),
        AST::Identifier::make("u32"_s)
    );
    type.m_inferredType = m_shaderModule.types().u32Type();

    auto& builtinAttribute = m_shaderModule.astBuilder().construct<AST::BuiltinAttribute>(
        SourceSpan::empty(),
        Builtin::LocalInvocationIndex
    );

    auto& parameter = m_shaderModule.astBuilder().construct<AST::Parameter>(
        SourceSpan::empty(),
        AST::Identifier::make("__localInvocationIndex"_s),
        type,
        AST::Attribute::List { builtinAttribute },
        AST::ParameterRole::UserDefined
    );

    m_shaderModule.append(function.parameters(), parameter);

    return parameter.name();
}

AST::Statement::List RewriteGlobalVariables::storeInitialValue(const UsedPrivateGlobals& globals)
{
    AST::Statement::List statements;
    for (auto* global : globals) {
        auto& variable = *global->declaration;

        if (auto addressSpace = variable.addressSpace(); !addressSpace.has_value() || *addressSpace != AddressSpace::Workgroup)
            continue;

        auto* type = variable.storeType();
        auto& target = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
            SourceSpan::empty(),
            AST::Identifier::make(variable.name().id())
        );
        target.m_inferredType = type;
        storeInitialValue(target, statements, 0);
    }
    return statements;
}

void RewriteGlobalVariables::storeInitialValue(AST::Expression& target, AST::Statement::List& statements, unsigned arrayDepth)
{
    const auto& zeroInitialize = [&]() {
        // This piece of code generation relies on 2 implementation details from the metal serializer:
        // - The callee's name won't be used if the call is set to constructor
        // - There's a special case to handle the case where the left-hand side
        //   of the assignment doesn't have a type, so we can erase it
        auto& callee = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("__initialize"_s));
        callee.m_inferredType = target.inferredType();

        auto& call = m_shaderModule.astBuilder().construct<AST::CallExpression>(
            SourceSpan::empty(),
            callee,
            AST::Expression::List { }
        );
        call.m_inferredType = target.inferredType();
        call.m_isConstructor = true;

        target.m_inferredType = nullptr;

        auto& assignmentStatement = m_shaderModule.astBuilder().construct<AST::AssignmentStatement>(
            SourceSpan::empty(),
            target,
            call
        );
        statements.append(AST::Statement::Ref(assignmentStatement));
    };

    auto* type = target.inferredType();
    if (auto* arrayType = std::get_if<Types::Array>(type)) {
        RELEASE_ASSERT(!arrayType->isRuntimeSized());
        String indexVariableName = makeString("__i"_s, arrayDepth);

        auto& indexVariable = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(
            SourceSpan::empty(),
            AST::Identifier::make(indexVariableName)
        );
        indexVariable.m_inferredType = m_shaderModule.types().u32Type();

        auto& arrayAccess = m_shaderModule.astBuilder().construct<AST::IndexAccessExpression>(
            SourceSpan::empty(),
            target,
            indexVariable
        );
        arrayAccess.m_inferredType = arrayType->element;

        AST::Statement::List forBodyStatements;
        storeInitialValue(arrayAccess, forBodyStatements, arrayDepth + 1);

        auto& zero = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
            SourceSpan::empty(),
            0
        );
        zero.m_inferredType = m_shaderModule.types().u32Type();

        auto& forVariable = m_shaderModule.astBuilder().construct<AST::Variable>(
            SourceSpan::empty(),
            AST::VariableFlavor::Var,
            AST::Identifier::make(indexVariableName),
            nullptr,
            &zero
        );

        auto& forInitializer = m_shaderModule.astBuilder().construct<AST::VariableStatement>(
            SourceSpan::empty(),
            forVariable
        );

        auto* arrayLength = [&]() -> AST::Expression* {
            if (auto* overrideExpression = std::get_if<AST::Expression*>(&arrayType->size))
                return *overrideExpression;

            auto& arrayLength = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
                SourceSpan::empty(),
                std::get<unsigned>(arrayType->size)
            );
            arrayLength.m_inferredType = m_shaderModule.types().u32Type();
            return &arrayLength;
        }();


        auto& forTest = m_shaderModule.astBuilder().construct<AST::BinaryExpression>(
            SourceSpan::empty(),
            indexVariable,
            *arrayLength,
            AST::BinaryOperation::LessThan
        );
        forTest.m_inferredType = m_shaderModule.types().boolType();

        auto& one = m_shaderModule.astBuilder().construct<AST::Unsigned32Literal>(
            SourceSpan::empty(),
            1
        );
        one.m_inferredType = m_shaderModule.types().u32Type();

        auto& forUpdate = m_shaderModule.astBuilder().construct<AST::CompoundAssignmentStatement>(
            SourceSpan::empty(),
            indexVariable,
            one,
            AST::BinaryOperation::Add
        );

        auto& forBody = m_shaderModule.astBuilder().construct<AST::CompoundStatement>(
            SourceSpan::empty(),
            AST::Attribute::List { },
            WTFMove(forBodyStatements)
        );

        auto& forStatement = m_shaderModule.astBuilder().construct<AST::ForStatement>(
            SourceSpan::empty(),
            &forInitializer,
            &forTest,
            &forUpdate,
            forBody
        );
        forStatement.setInternallyGenerated();

        statements.append(AST::Statement::Ref(forStatement));
        return;
    }

    if (auto* structType = std::get_if<Types::Struct>(type)) {
        if (type->isConstructible()) {
            zeroInitialize();
            return;
        }

        for (auto& member : structType->structure.members()) {
            auto* fieldType = member.type().inferredType();
            auto& fieldAccess = m_shaderModule.astBuilder().construct<AST::FieldAccessExpression>(
                SourceSpan::empty(),
                target,
                AST::Identifier::make(member.name())
            );
            fieldAccess.m_inferredType = fieldType;
            storeInitialValue(fieldAccess, statements, arrayDepth);
        }
        return;
    }

    if (type && std::holds_alternative<Types::Atomic>(*type)) {
        auto& callee = m_shaderModule.astBuilder().construct<AST::IdentifierExpression>(SourceSpan::empty(), AST::Identifier::make("atomicStore"_s));
        callee.m_inferredType = m_shaderModule.types().voidType();

        auto& pointer = m_shaderModule.astBuilder().construct<AST::UnaryExpression>(
            SourceSpan::empty(),
            target,
            AST::UnaryOperation::AddressOf
        );
        pointer.m_inferredType = m_shaderModule.types().voidType();

        auto& value = m_shaderModule.astBuilder().construct<AST::AbstractIntegerLiteral>(SourceSpan::empty(), 0);
        value.m_inferredType = m_shaderModule.types().abstractIntType();

        auto& call = m_shaderModule.astBuilder().construct<AST::CallExpression>(
            SourceSpan::empty(),
            callee,
            AST::Expression::List { pointer, value }
        );
        call.m_inferredType = m_shaderModule.types().voidType();

        auto& callStatement = m_shaderModule.astBuilder().construct<AST::CallStatement>(
            SourceSpan::empty(),
            call
        );
        statements.append(AST::Statement::Ref(callStatement));
        return;
    }

    zeroInitialize();
}

void RewriteGlobalVariables::def(const AST::Identifier& name, AST::Variable* variable)
{
    dataLogLnIf(shouldLogGlobalVariableRewriting, "> def: ", name, " at line:", name.span().line, " column: ", name.span().lineOffset);
    m_defs.add(name, variable);
}

auto RewriteGlobalVariables::readVariable(AST::IdentifierExpression& identifier) -> const Global*
{
    auto def = m_defs.find(identifier.identifier());
    if (def != m_defs.end())
        return nullptr;

    auto it = m_globals.find(identifier.identifier());
    if (it == m_globals.end())
        return nullptr;

    auto& global = it->value;
    if (global.declaration->flavor() == AST::VariableFlavor::Const)
        return nullptr;

    dataLogLnIf(shouldLogGlobalVariableRewriting, "> read global: ", identifier.identifier(), " at line:", identifier.span().line, " column: ", identifier.span().lineOffset);
    auto addResult = m_reads.add(identifier.identifier());
    if (addResult.isNewEntry) {
        if (auto* type = global.declaration->maybeTypeName())
            visit(*type);
        if (auto* initializer = global.declaration->maybeInitializer())
            visit(*initializer);
    }

    return &global;
}

void RewriteGlobalVariables::insertBeforeCurrentStatement(AST::Statement& statement)
{
    m_pendingInsertions.append({ &statement, m_currentStatementIndex });
}

AST::Identifier RewriteGlobalVariables::argumentBufferParameterName(unsigned group)
{
    return AST::Identifier::make(makeString("__ArgumentBuffer_"_s, group));
}

AST::Identifier RewriteGlobalVariables::argumentBufferStructName(unsigned group)
{
    return AST::Identifier::make(makeString("__ArgumentBufferT_"_s, m_entryPointID, "_"_s, group));
}

AST::Identifier RewriteGlobalVariables::dynamicOffsetVariableName()
{
    return AST::Identifier::make("__DynamicOffsets"_str);
}

std::optional<Error> rewriteGlobalVariables(ShaderModule& shaderModule, const HashMap<String, PipelineLayout*>& pipelineLayouts, HashMap<String, Reflection::EntryPointInformation>& entryPointInformations)
{
    return RewriteGlobalVariables(shaderModule, pipelineLayouts, entryPointInformations).run();
}

} // namespace WGSL
