// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/resolver/resolver.h"

#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits>
#include <utility>

#include "src/tint/ast/alias.h"
#include "src/tint/ast/array.h"
#include "src/tint/ast/assignment_statement.h"
#include "src/tint/ast/bitcast_expression.h"
#include "src/tint/ast/break_statement.h"
#include "src/tint/ast/call_statement.h"
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/depth_texture.h"
#include "src/tint/ast/disable_validation_attribute.h"
#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/fallthrough_statement.h"
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/internal_attribute.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/loop_statement.h"
#include "src/tint/ast/matrix.h"
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/sampler.h"
#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/ast/type_name.h"
#include "src/tint/ast/unary_op_expression.h"
#include "src/tint/ast/variable_decl_statement.h"
#include "src/tint/ast/vector.h"
#include "src/tint/ast/workgroup_attribute.h"
#include "src/tint/resolver/uniformity.h"
#include "src/tint/sem/array.h"
#include "src/tint/sem/atomic.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/depth_multisampled_texture.h"
#include "src/tint/sem/depth_texture.h"
#include "src/tint/sem/for_loop_statement.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/if_statement.h"
#include "src/tint/sem/loop_statement.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/module.h"
#include "src/tint/sem/multisampled_texture.h"
#include "src/tint/sem/pointer.h"
#include "src/tint/sem/reference.h"
#include "src/tint/sem/sampled_texture.h"
#include "src/tint/sem/sampler.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/storage_texture.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/switch_statement.h"
#include "src/tint/sem/type_constructor.h"
#include "src/tint/sem/type_conversion.h"
#include "src/tint/sem/variable.h"
#include "src/tint/utils/defer.h"
#include "src/tint/utils/math.h"
#include "src/tint/utils/reverse.h"
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/utils/transform.h"

namespace tint::resolver {

Resolver::Resolver(ProgramBuilder* builder)
    : builder_(builder),
      diagnostics_(builder->Diagnostics()),
      intrinsic_table_(IntrinsicTable::Create(*builder)),
      sem_(builder, dependencies_),
      validator_(builder, sem_) {}

Resolver::~Resolver() = default;

bool Resolver::Resolve() {
    if (builder_->Diagnostics().contains_errors()) {
        return false;
    }

    if (!DependencyGraph::Build(builder_->AST(), builder_->Symbols(), builder_->Diagnostics(),
                                dependencies_)) {
        return false;
    }

    // Create the semantic module
    builder_->Sem().SetModule(builder_->create<sem::Module>(dependencies_.ordered_globals));

    bool result = ResolveInternal();

    if (!result && !diagnostics_.contains_errors()) {
        TINT_ICE(Resolver, diagnostics_) << "resolving failed, but no error was raised";
        return false;
    }

    return result;
}

bool Resolver::ResolveInternal() {
    Mark(&builder_->AST());

    // Process all module-scope declarations in dependency order.
    for (auto* decl : dependencies_.ordered_globals) {
        Mark(decl);
        // Enable directives don't have sem node.
        if (decl->Is<ast::Enable>()) {
            continue;
        }
        if (!Switch(
                decl,  //
                [&](const ast::TypeDecl* td) { return TypeDecl(td); },
                [&](const ast::Function* func) { return Function(func); },
                [&](const ast::Variable* var) { return GlobalVariable(var); },
                [&](Default) {
                    TINT_UNREACHABLE(Resolver, diagnostics_)
                        << "unhandled global declaration: " << decl->TypeInfo().name;
                    return nullptr;
                })) {
            return false;
        }
    }

    AllocateOverridableConstantIds();

    SetShadows();

    if (!validator_.PipelineStages(entry_points_)) {
        return false;
    }

    if (!AnalyzeUniformity(builder_, dependencies_)) {
        // TODO(jrprice): Reject programs that fail uniformity analysis.
    }

    bool result = true;
    for (auto* node : builder_->ASTNodes().Objects()) {
        if (marked_.count(node) == 0) {
            TINT_ICE(Resolver, diagnostics_)
                << "AST node '" << node->TypeInfo().name << "' was not reached by the resolver\n"
                << "At: " << node->source << "\n"
                << "Pointer: " << node;
            result = false;
        }
    }

    return result;
}

sem::Type* Resolver::Type(const ast::Type* ty) {
    Mark(ty);
    auto* s = Switch(
        ty,  //
        [&](const ast::Void*) { return builder_->create<sem::Void>(); },
        [&](const ast::Bool*) { return builder_->create<sem::Bool>(); },
        [&](const ast::I32*) { return builder_->create<sem::I32>(); },
        [&](const ast::U32*) { return builder_->create<sem::U32>(); },
        [&](const ast::F32*) { return builder_->create<sem::F32>(); },
        [&](const ast::Vector* t) -> sem::Vector* {
            if (!t->type) {
                AddError("missing vector element type", t->source.End());
                return nullptr;
            }
            if (auto* el = Type(t->type)) {
                if (auto* vector = builder_->create<sem::Vector>(el, t->width)) {
                    if (validator_.Vector(vector, t->source)) {
                        return vector;
                    }
                }
            }
            return nullptr;
        },
        [&](const ast::Matrix* t) -> sem::Matrix* {
            if (!t->type) {
                AddError("missing matrix element type", t->source.End());
                return nullptr;
            }
            if (auto* el = Type(t->type)) {
                if (auto* column_type = builder_->create<sem::Vector>(el, t->rows)) {
                    if (auto* matrix = builder_->create<sem::Matrix>(column_type, t->columns)) {
                        if (validator_.Matrix(matrix, t->source)) {
                            return matrix;
                        }
                    }
                }
            }
            return nullptr;
        },
        [&](const ast::Array* t) { return Array(t); },
        [&](const ast::Atomic* t) -> sem::Atomic* {
            if (auto* el = Type(t->type)) {
                auto* a = builder_->create<sem::Atomic>(el);
                if (!validator_.Atomic(t, a)) {
                    return nullptr;
                }
                return a;
            }
            return nullptr;
        },
        [&](const ast::Pointer* t) -> sem::Pointer* {
            if (auto* el = Type(t->type)) {
                auto access = t->access;
                if (access == ast::kUndefined) {
                    access = DefaultAccessForStorageClass(t->storage_class);
                }
                return builder_->create<sem::Pointer>(el, t->storage_class, access);
            }
            return nullptr;
        },
        [&](const ast::Sampler* t) { return builder_->create<sem::Sampler>(t->kind); },
        [&](const ast::SampledTexture* t) -> sem::SampledTexture* {
            if (auto* el = Type(t->type)) {
                return builder_->create<sem::SampledTexture>(t->dim, el);
            }
            return nullptr;
        },
        [&](const ast::MultisampledTexture* t) -> sem::MultisampledTexture* {
            if (auto* el = Type(t->type)) {
                return builder_->create<sem::MultisampledTexture>(t->dim, el);
            }
            return nullptr;
        },
        [&](const ast::DepthTexture* t) { return builder_->create<sem::DepthTexture>(t->dim); },
        [&](const ast::DepthMultisampledTexture* t) {
            return builder_->create<sem::DepthMultisampledTexture>(t->dim);
        },
        [&](const ast::StorageTexture* t) -> sem::StorageTexture* {
            if (auto* el = Type(t->type)) {
                if (!validator_.StorageTexture(t)) {
                    return nullptr;
                }
                return builder_->create<sem::StorageTexture>(t->dim, t->format, t->access, el);
            }
            return nullptr;
        },
        [&](const ast::ExternalTexture*) { return builder_->create<sem::ExternalTexture>(); },
        [&](Default) {
            auto* resolved = sem_.ResolvedSymbol(ty);
            return Switch(
                resolved,  //
                [&](sem::Type* type) { return type; },
                [&](sem::Variable* var) {
                    auto name = builder_->Symbols().NameFor(var->Declaration()->symbol);
                    AddError("cannot use variable '" + name + "' as type", ty->source);
                    AddNote("'" + name + "' declared here", var->Declaration()->source);
                    return nullptr;
                },
                [&](sem::Function* func) {
                    auto name = builder_->Symbols().NameFor(func->Declaration()->symbol);
                    AddError("cannot use function '" + name + "' as type", ty->source);
                    AddNote("'" + name + "' declared here", func->Declaration()->source);
                    return nullptr;
                },
                [&](Default) {
                    if (auto* tn = ty->As<ast::TypeName>()) {
                        if (IsBuiltin(tn->name)) {
                            auto name = builder_->Symbols().NameFor(tn->name);
                            AddError("cannot use builtin '" + name + "' as type", ty->source);
                            return nullptr;
                        }
                    }
                    TINT_UNREACHABLE(Resolver, diagnostics_)
                        << "Unhandled resolved type '"
                        << (resolved ? resolved->TypeInfo().name : "<null>")
                        << "' resolved from ast::Type '" << ty->TypeInfo().name << "'";
                    return nullptr;
                });
        });

    if (s) {
        builder_->Sem().Add(ty, s);
    }
    return s;
}

sem::Variable* Resolver::Variable(const ast::Variable* var,
                                  VariableKind kind,
                                  uint32_t index /* = 0 */) {
    const sem::Type* storage_ty = nullptr;

    // If the variable has a declared type, resolve it.
    if (auto* ty = var->type) {
        storage_ty = Type(ty);
        if (!storage_ty) {
            return nullptr;
        }
    }

    const sem::Expression* rhs = nullptr;

    // Does the variable have a constructor?
    if (var->constructor) {
        rhs = Expression(var->constructor);
        if (!rhs) {
            return nullptr;
        }

        // If the variable has no declared type, infer it from the RHS
        if (!storage_ty) {
            if (!var->is_const && kind == VariableKind::kGlobal) {
                AddError("global var declaration must specify a type", var->source);
                return nullptr;
            }

            storage_ty = rhs->Type()->UnwrapRef();  // Implicit load of RHS
        }
    } else if (var->is_const && !var->is_overridable && kind != VariableKind::kParameter) {
        AddError("let declaration must have an initializer", var->source);
        return nullptr;
    } else if (!var->type) {
        AddError((kind == VariableKind::kGlobal)
                     ? "module scope var declaration requires a type and initializer"
                     : "function scope var declaration requires a type or initializer",
                 var->source);
        return nullptr;
    }

    if (!storage_ty) {
        TINT_ICE(Resolver, diagnostics_) << "failed to determine storage type for variable '" +
                                                builder_->Symbols().NameFor(var->symbol) + "'\n"
                                         << "Source: " << var->source;
        return nullptr;
    }

    auto storage_class = var->declared_storage_class;
    if (storage_class == ast::StorageClass::kNone && !var->is_const) {
        // No declared storage class. Infer from usage / type.
        if (kind == VariableKind::kLocal) {
            storage_class = ast::StorageClass::kFunction;
        } else if (storage_ty->UnwrapRef()->is_handle()) {
            // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
            // If the store type is a texture type or a sampler type, then the
            // variable declaration must not have a storage class attribute. The
            // storage class will always be handle.
            storage_class = ast::StorageClass::kHandle;
        }
    }

    if (kind == VariableKind::kLocal && !var->is_const &&
        storage_class != ast::StorageClass::kFunction &&
        validator_.IsValidationEnabled(var->attributes,
                                       ast::DisabledValidation::kIgnoreStorageClass)) {
        AddError("function variable has a non-function storage class", var->source);
        return nullptr;
    }

    auto access = var->declared_access;
    if (access == ast::Access::kUndefined) {
        access = DefaultAccessForStorageClass(storage_class);
    }

    auto* var_ty = storage_ty;
    if (!var->is_const) {
        // Variable declaration. Unlike `let`, `var` has storage.
        // Variables are always of a reference type to the declared storage type.
        var_ty = builder_->create<sem::Reference>(storage_ty, storage_class, access);
    }

    if (rhs && !validator_.VariableConstructorOrCast(var, storage_class, storage_ty, rhs->Type())) {
        return nullptr;
    }

    if (!ApplyStorageClassUsageToType(storage_class, const_cast<sem::Type*>(var_ty), var->source)) {
        AddNote(std::string("while instantiating ") +
                    ((kind == VariableKind::kParameter) ? "parameter " : "variable ") +
                    builder_->Symbols().NameFor(var->symbol),
                var->source);
        return nullptr;
    }

    if (kind == VariableKind::kParameter) {
        if (auto* ptr = var_ty->As<sem::Pointer>()) {
            // For MSL, we push module-scope variables into the entry point as pointer
            // parameters, so we also need to handle their store type.
            if (!ApplyStorageClassUsageToType(
                    ptr->StorageClass(), const_cast<sem::Type*>(ptr->StoreType()), var->source)) {
                AddNote("while instantiating parameter " + builder_->Symbols().NameFor(var->symbol),
                        var->source);
                return nullptr;
            }
        }
    }

    switch (kind) {
        case VariableKind::kGlobal: {
            sem::BindingPoint binding_point;
            if (auto bp = var->BindingPoint()) {
                binding_point = {bp.group->value, bp.binding->value};
            }

            bool has_const_val = rhs && var->is_const && !var->is_overridable;
            auto* global = builder_->create<sem::GlobalVariable>(
                var, var_ty, storage_class, access,
                has_const_val ? rhs->ConstantValue() : sem::Constant{}, binding_point);

            if (var->is_overridable) {
                global->SetIsOverridable();
                if (auto* id = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
                    global->SetConstantId(static_cast<uint16_t>(id->value));
                }
            }

            global->SetConstructor(rhs);

            builder_->Sem().Add(var, global);
            return global;
        }
        case VariableKind::kLocal: {
            auto* local = builder_->create<sem::LocalVariable>(
                var, var_ty, storage_class, access, current_statement_,
                (rhs && var->is_const) ? rhs->ConstantValue() : sem::Constant{});
            builder_->Sem().Add(var, local);
            local->SetConstructor(rhs);
            return local;
        }
        case VariableKind::kParameter: {
            auto* param =
                builder_->create<sem::Parameter>(var, index, var_ty, storage_class, access);
            builder_->Sem().Add(var, param);
            return param;
        }
    }

    TINT_UNREACHABLE(Resolver, diagnostics_) << "unhandled VariableKind " << static_cast<int>(kind);
    return nullptr;
}

ast::Access Resolver::DefaultAccessForStorageClass(ast::StorageClass storage_class) {
    // https://gpuweb.github.io/gpuweb/wgsl/#storage-class
    switch (storage_class) {
        case ast::StorageClass::kStorage:
        case ast::StorageClass::kUniform:
        case ast::StorageClass::kHandle:
            return ast::Access::kRead;
        default:
            break;
    }
    return ast::Access::kReadWrite;
}

void Resolver::AllocateOverridableConstantIds() {
    // The next pipeline constant ID to try to allocate.
    uint16_t next_constant_id = 0;

    // Allocate constant IDs in global declaration order, so that they are
    // deterministic.
    // TODO(crbug.com/tint/1192): If a transform changes the order or removes an
    // unused constant, the allocation may change on the next Resolver pass.
    for (auto* decl : builder_->AST().GlobalDeclarations()) {
        auto* var = decl->As<ast::Variable>();
        if (!var || !var->is_overridable) {
            continue;
        }

        uint16_t constant_id;
        if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
            constant_id = static_cast<uint16_t>(id_attr->value);
        } else {
            // No ID was specified, so allocate the next available ID.
            constant_id = next_constant_id;
            while (constant_ids_.count(constant_id)) {
                if (constant_id == UINT16_MAX) {
                    TINT_ICE(Resolver, builder_->Diagnostics())
                        << "no more pipeline constant IDs available";
                    return;
                }
                constant_id++;
            }
            next_constant_id = constant_id + 1;
        }

        auto* sem = sem_.Get<sem::GlobalVariable>(var);
        const_cast<sem::GlobalVariable*>(sem)->SetConstantId(constant_id);
    }
}

void Resolver::SetShadows() {
    for (auto it : dependencies_.shadows) {
        Switch(
            sem_.Get(it.first),  //
            [&](sem::LocalVariable* local) { local->SetShadows(sem_.Get(it.second)); },
            [&](sem::Parameter* param) { param->SetShadows(sem_.Get(it.second)); });
    }
}

sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* var) {
    auto* sem = Variable(var, VariableKind::kGlobal);
    if (!sem) {
        return nullptr;
    }

    auto storage_class = sem->StorageClass();
    if (!var->is_const && storage_class == ast::StorageClass::kNone) {
        AddError("global variables must have a storage class", var->source);
        return nullptr;
    }
    if (var->is_const && storage_class != ast::StorageClass::kNone) {
        AddError("global constants shouldn't have a storage class", var->source);
        return nullptr;
    }

    for (auto* attr : var->attributes) {
        Mark(attr);

        if (auto* id_attr = attr->As<ast::IdAttribute>()) {
            // Track the constant IDs that are specified in the shader.
            constant_ids_.emplace(id_attr->value, sem);
        }
    }

    if (!validator_.NoDuplicateAttributes(var->attributes)) {
        return nullptr;
    }

    if (!validator_.GlobalVariable(sem, constant_ids_, atomic_composite_info_)) {
        return nullptr;
    }

    // TODO(bclayton): Call this at the end of resolve on all uniform and storage
    // referenced structs
    if (!validator_.StorageClassLayout(sem, valid_type_storage_layouts_)) {
        return nullptr;
    }

    return sem->As<sem::GlobalVariable>();
}

sem::Function* Resolver::Function(const ast::Function* decl) {
    uint32_t parameter_index = 0;
    std::unordered_map<Symbol, Source> parameter_names;
    std::vector<sem::Parameter*> parameters;

    // Resolve all the parameters
    for (auto* param : decl->params) {
        Mark(param);

        {  // Check the parameter name is unique for the function
            auto emplaced = parameter_names.emplace(param->symbol, param->source);
            if (!emplaced.second) {
                auto name = builder_->Symbols().NameFor(param->symbol);
                AddError("redefinition of parameter '" + name + "'", param->source);
                AddNote("previous definition is here", emplaced.first->second);
                return nullptr;
            }
        }

        auto* var =
            As<sem::Parameter>(Variable(param, VariableKind::kParameter, parameter_index++));
        if (!var) {
            return nullptr;
        }

        for (auto* attr : param->attributes) {
            Mark(attr);
        }
        if (!validator_.NoDuplicateAttributes(param->attributes)) {
            return nullptr;
        }

        parameters.emplace_back(var);

        auto* var_ty = const_cast<sem::Type*>(var->Type());
        if (auto* str = var_ty->As<sem::Struct>()) {
            switch (decl->PipelineStage()) {
                case ast::PipelineStage::kVertex:
                    str->AddUsage(sem::PipelineStageUsage::kVertexInput);
                    break;
                case ast::PipelineStage::kFragment:
                    str->AddUsage(sem::PipelineStageUsage::kFragmentInput);
                    break;
                case ast::PipelineStage::kCompute:
                    str->AddUsage(sem::PipelineStageUsage::kComputeInput);
                    break;
                case ast::PipelineStage::kNone:
                    break;
            }
        }
    }

    // Resolve the return type
    sem::Type* return_type = nullptr;
    if (auto* ty = decl->return_type) {
        return_type = Type(ty);
        if (!return_type) {
            return nullptr;
        }
    } else {
        return_type = builder_->create<sem::Void>();
    }

    if (auto* str = return_type->As<sem::Struct>()) {
        if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, str, decl->source)) {
            AddNote(
                "while instantiating return type for " + builder_->Symbols().NameFor(decl->symbol),
                decl->source);
            return nullptr;
        }

        switch (decl->PipelineStage()) {
            case ast::PipelineStage::kVertex:
                str->AddUsage(sem::PipelineStageUsage::kVertexOutput);
                break;
            case ast::PipelineStage::kFragment:
                str->AddUsage(sem::PipelineStageUsage::kFragmentOutput);
                break;
            case ast::PipelineStage::kCompute:
                str->AddUsage(sem::PipelineStageUsage::kComputeOutput);
                break;
            case ast::PipelineStage::kNone:
                break;
        }
    }

    auto* func = builder_->create<sem::Function>(decl, return_type, parameters);
    builder_->Sem().Add(decl, func);

    TINT_SCOPED_ASSIGNMENT(current_function_, func);

    if (!WorkgroupSize(decl)) {
        return nullptr;
    }

    if (decl->IsEntryPoint()) {
        entry_points_.emplace_back(func);
    }

    if (decl->body) {
        Mark(decl->body);
        if (current_compound_statement_) {
            TINT_ICE(Resolver, diagnostics_)
                << "Resolver::Function() called with a current compound statement";
            return nullptr;
        }
        auto* body = StatementScope(decl->body, builder_->create<sem::FunctionBlockStatement>(func),
                                    [&] { return Statements(decl->body->statements); });
        if (!body) {
            return nullptr;
        }
        func->Behaviors() = body->Behaviors();
        if (func->Behaviors().Contains(sem::Behavior::kReturn)) {
            // https://www.w3.org/TR/WGSL/#behaviors-rules
            // We assign a behavior to each function: it is its body’s behavior
            // (treating the body as a regular statement), with any "Return" replaced
            // by "Next".
            func->Behaviors().Remove(sem::Behavior::kReturn);
            func->Behaviors().Add(sem::Behavior::kNext);
        }
    }

    for (auto* attr : decl->attributes) {
        Mark(attr);
    }
    if (!validator_.NoDuplicateAttributes(decl->attributes)) {
        return nullptr;
    }

    for (auto* attr : decl->return_type_attributes) {
        Mark(attr);
    }
    if (!validator_.NoDuplicateAttributes(decl->return_type_attributes)) {
        return nullptr;
    }

    auto stage = current_function_ ? current_function_->Declaration()->PipelineStage()
                                   : ast::PipelineStage::kNone;
    if (!validator_.Function(func, stage)) {
        return nullptr;
    }

    // If this is an entry point, mark all transitively called functions as being
    // used by this entry point.
    if (decl->IsEntryPoint()) {
        for (auto* f : func->TransitivelyCalledFunctions()) {
            const_cast<sem::Function*>(f)->AddAncestorEntryPoint(func);
        }
    }

    return func;
}

bool Resolver::WorkgroupSize(const ast::Function* func) {
    // Set work-group size defaults.
    sem::WorkgroupSize ws;
    for (int i = 0; i < 3; i++) {
        ws[i].value = 1;
        ws[i].overridable_const = nullptr;
    }

    auto* attr = ast::GetAttribute<ast::WorkgroupAttribute>(func->attributes);
    if (!attr) {
        return true;
    }

    auto values = attr->Values();
    auto any_i32 = false;
    auto any_u32 = false;
    for (int i = 0; i < 3; i++) {
        // Each argument to this attribute can either be a literal, an
        // identifier for a module-scope constants, or nullptr if not specified.

        auto* expr = values[i];
        if (!expr) {
            // Not specified, just use the default.
            continue;
        }

        auto* expr_sem = Expression(expr);
        if (!expr_sem) {
            return false;
        }

        constexpr const char* kErrBadType =
            "workgroup_size argument must be either literal or module-scope "
            "constant of type i32 or u32";
        constexpr const char* kErrInconsistentType =
            "workgroup_size arguments must be of the same type, either i32 "
            "or u32";

        auto* ty = sem_.TypeOf(expr);
        bool is_i32 = ty->UnwrapRef()->Is<sem::I32>();
        bool is_u32 = ty->UnwrapRef()->Is<sem::U32>();
        if (!is_i32 && !is_u32) {
            AddError(kErrBadType, expr->source);
            return false;
        }

        any_i32 = any_i32 || is_i32;
        any_u32 = any_u32 || is_u32;
        if (any_i32 && any_u32) {
            AddError(kErrInconsistentType, expr->source);
            return false;
        }

        sem::Constant value;

        if (auto* user = sem_.Get(expr)->As<sem::VariableUser>()) {
            // We have an variable of a module-scope constant.
            auto* decl = user->Variable()->Declaration();
            if (!decl->is_const) {
                AddError(kErrBadType, expr->source);
                return false;
            }
            // Capture the constant if it is pipeline-overridable.
            if (decl->is_overridable) {
                ws[i].overridable_const = decl;
            }

            if (decl->constructor) {
                value = sem_.Get(decl->constructor)->ConstantValue();
            } else {
                // No constructor means this value must be overriden by the user.
                ws[i].value = 0;
                continue;
            }
        } else if (expr->Is<ast::LiteralExpression>()) {
            value = sem_.Get(expr)->ConstantValue();
        } else {
            AddError(
                "workgroup_size argument must be either a literal or a "
                "module-scope constant",
                values[i]->source);
            return false;
        }

        if (!value) {
            TINT_ICE(Resolver, diagnostics_)
                << "could not resolve constant workgroup_size constant value";
            continue;
        }
        // validator_.Validate and set the default value for this dimension.
        if (is_i32 ? value.Elements()[0].i32 < 1 : value.Elements()[0].u32 < 1) {
            AddError("workgroup_size argument must be at least 1", values[i]->source);
            return false;
        }

        ws[i].value =
            is_i32 ? static_cast<uint32_t>(value.Elements()[0].i32) : value.Elements()[0].u32;
    }

    current_function_->SetWorkgroupSize(std::move(ws));
    return true;
}

bool Resolver::Statements(const ast::StatementList& stmts) {
    sem::Behaviors behaviors{sem::Behavior::kNext};

    bool reachable = true;
    for (auto* stmt : stmts) {
        Mark(stmt);
        auto* sem = Statement(stmt);
        if (!sem) {
            return false;
        }
        // s1 s2:(B1∖{Next}) ∪ B2
        sem->SetIsReachable(reachable);
        if (reachable) {
            behaviors = (behaviors - sem::Behavior::kNext) + sem->Behaviors();
        }
        reachable = reachable && sem->Behaviors().Contains(sem::Behavior::kNext);
    }

    current_statement_->Behaviors() = behaviors;

    if (!validator_.Statements(stmts)) {
        return false;
    }

    return true;
}

sem::Statement* Resolver::Statement(const ast::Statement* stmt) {
    return Switch(
        stmt,
        // Compound statements. These create their own sem::CompoundStatement
        // bindings.
        [&](const ast::BlockStatement* b) { return BlockStatement(b); },
        [&](const ast::ForLoopStatement* l) { return ForLoopStatement(l); },
        [&](const ast::LoopStatement* l) { return LoopStatement(l); },
        [&](const ast::IfStatement* i) { return IfStatement(i); },
        [&](const ast::SwitchStatement* s) { return SwitchStatement(s); },

        // Non-Compound statements
        [&](const ast::AssignmentStatement* a) { return AssignmentStatement(a); },
        [&](const ast::BreakStatement* b) { return BreakStatement(b); },
        [&](const ast::CallStatement* c) { return CallStatement(c); },
        [&](const ast::CompoundAssignmentStatement* c) { return CompoundAssignmentStatement(c); },
        [&](const ast::ContinueStatement* c) { return ContinueStatement(c); },
        [&](const ast::DiscardStatement* d) { return DiscardStatement(d); },
        [&](const ast::FallthroughStatement* f) { return FallthroughStatement(f); },
        [&](const ast::IncrementDecrementStatement* i) { return IncrementDecrementStatement(i); },
        [&](const ast::ReturnStatement* r) { return ReturnStatement(r); },
        [&](const ast::VariableDeclStatement* v) { return VariableDeclStatement(v); },

        // Error cases
        [&](const ast::CaseStatement*) {
            AddError("case statement can only be used inside a switch statement", stmt->source);
            return nullptr;
        },
        [&](Default) {
            AddError("unknown statement type: " + std::string(stmt->TypeInfo().name), stmt->source);
            return nullptr;
        });
}

sem::CaseStatement* Resolver::CaseStatement(const ast::CaseStatement* stmt) {
    auto* sem =
        builder_->create<sem::CaseStatement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        for (auto* sel : stmt->selectors) {
            if (!Expression(sel)) {
                return false;
            }
        }
        Mark(stmt->body);
        auto* body = BlockStatement(stmt->body);
        if (!body) {
            return false;
        }
        sem->SetBlock(body);
        sem->Behaviors() = body->Behaviors();
        return true;
    });
}

sem::IfStatement* Resolver::IfStatement(const ast::IfStatement* stmt) {
    auto* sem =
        builder_->create<sem::IfStatement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        auto* cond = Expression(stmt->condition);
        if (!cond) {
            return false;
        }
        sem->SetCondition(cond);
        sem->Behaviors() = cond->Behaviors();
        sem->Behaviors().Remove(sem::Behavior::kNext);

        Mark(stmt->body);
        auto* body = builder_->create<sem::BlockStatement>(stmt->body, current_compound_statement_,
                                                           current_function_);
        if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) {
            return false;
        }
        sem->Behaviors().Add(body->Behaviors());

        if (stmt->else_statement) {
            Mark(stmt->else_statement);
            auto* else_sem = Statement(stmt->else_statement);
            if (!else_sem) {
                return false;
            }
            sem->Behaviors().Add(else_sem->Behaviors());
        } else {
            // https://www.w3.org/TR/WGSL/#behaviors-rules
            // if statements without an else branch are treated as if they had an
            // empty else branch (which adds Next to their behavior)
            sem->Behaviors().Add(sem::Behavior::kNext);
        }

        return validator_.IfStatement(sem);
    });
}

sem::BlockStatement* Resolver::BlockStatement(const ast::BlockStatement* stmt) {
    auto* sem = builder_->create<sem::BlockStatement>(
        stmt->As<ast::BlockStatement>(), current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] { return Statements(stmt->statements); });
}

sem::LoopStatement* Resolver::LoopStatement(const ast::LoopStatement* stmt) {
    auto* sem =
        builder_->create<sem::LoopStatement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        Mark(stmt->body);

        auto* body = builder_->create<sem::LoopBlockStatement>(
            stmt->body, current_compound_statement_, current_function_);
        return StatementScope(stmt->body, body, [&] {
            if (!Statements(stmt->body->statements)) {
                return false;
            }
            auto& behaviors = sem->Behaviors();
            behaviors = body->Behaviors();

            if (stmt->continuing) {
                Mark(stmt->continuing);
                auto* continuing = StatementScope(
                    stmt->continuing,
                    builder_->create<sem::LoopContinuingBlockStatement>(
                        stmt->continuing, current_compound_statement_, current_function_),
                    [&] { return Statements(stmt->continuing->statements); });
                if (!continuing) {
                    return false;
                }
                behaviors.Add(continuing->Behaviors());
            }

            if (behaviors.Contains(sem::Behavior::kBreak)) {  // Does the loop exit?
                behaviors.Add(sem::Behavior::kNext);
            } else {
                behaviors.Remove(sem::Behavior::kNext);
            }
            behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kContinue);

            return validator_.LoopStatement(sem);
        });
    });
}

sem::ForLoopStatement* Resolver::ForLoopStatement(const ast::ForLoopStatement* stmt) {
    auto* sem = builder_->create<sem::ForLoopStatement>(stmt, current_compound_statement_,
                                                        current_function_);
    return StatementScope(stmt, sem, [&] {
        auto& behaviors = sem->Behaviors();
        if (auto* initializer = stmt->initializer) {
            Mark(initializer);
            auto* init = Statement(initializer);
            if (!init) {
                return false;
            }
            behaviors.Add(init->Behaviors());
        }

        if (auto* cond_expr = stmt->condition) {
            auto* cond = Expression(cond_expr);
            if (!cond) {
                return false;
            }
            sem->SetCondition(cond);
            behaviors.Add(cond->Behaviors());
        }

        if (auto* continuing = stmt->continuing) {
            Mark(continuing);
            auto* cont = Statement(continuing);
            if (!cont) {
                return false;
            }
            behaviors.Add(cont->Behaviors());
        }

        Mark(stmt->body);

        auto* body = builder_->create<sem::LoopBlockStatement>(
            stmt->body, current_compound_statement_, current_function_);
        if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) {
            return false;
        }

        behaviors.Add(body->Behaviors());
        if (stmt->condition || behaviors.Contains(sem::Behavior::kBreak)) {  // Does the loop exit?
            behaviors.Add(sem::Behavior::kNext);
        } else {
            behaviors.Remove(sem::Behavior::kNext);
        }
        behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kContinue);

        return validator_.ForLoopStatement(sem);
    });
}

sem::Expression* Resolver::Expression(const ast::Expression* root) {
    std::vector<const ast::Expression*> sorted;
    bool mark_failed = false;
    if (!ast::TraverseExpressions<ast::TraverseOrder::RightToLeft>(
            root, diagnostics_, [&](const ast::Expression* expr) {
                if (!Mark(expr)) {
                    mark_failed = true;
                    return ast::TraverseAction::Stop;
                }
                sorted.emplace_back(expr);
                return ast::TraverseAction::Descend;
            })) {
        return nullptr;
    }

    if (mark_failed) {
        return nullptr;
    }

    for (auto* expr : utils::Reverse(sorted)) {
        auto* sem_expr = Switch(
            expr,
            [&](const ast::IndexAccessorExpression* array) -> sem::Expression* {
                return IndexAccessor(array);
            },
            [&](const ast::BinaryExpression* bin_op) -> sem::Expression* { return Binary(bin_op); },
            [&](const ast::BitcastExpression* bitcast) -> sem::Expression* {
                return Bitcast(bitcast);
            },
            [&](const ast::CallExpression* call) -> sem::Expression* { return Call(call); },
            [&](const ast::IdentifierExpression* ident) -> sem::Expression* {
                return Identifier(ident);
            },
            [&](const ast::LiteralExpression* literal) -> sem::Expression* {
                return Literal(literal);
            },
            [&](const ast::MemberAccessorExpression* member) -> sem::Expression* {
                return MemberAccessor(member);
            },
            [&](const ast::UnaryOpExpression* unary) -> sem::Expression* { return UnaryOp(unary); },
            [&](const ast::PhonyExpression*) -> sem::Expression* {
                return builder_->create<sem::Expression>(expr, builder_->create<sem::Void>(),
                                                         current_statement_, sem::Constant{},
                                                         /* has_side_effects */ false);
            },
            [&](Default) {
                TINT_ICE(Resolver, diagnostics_)
                    << "unhandled expression type: " << expr->TypeInfo().name;
                return nullptr;
            });
        if (!sem_expr) {
            return nullptr;
        }

        builder_->Sem().Add(expr, sem_expr);
        if (expr == root) {
            return sem_expr;
        }
    }

    TINT_ICE(Resolver, diagnostics_) << "Expression() did not find root node";
    return nullptr;
}

sem::Expression* Resolver::IndexAccessor(const ast::IndexAccessorExpression* expr) {
    auto* idx = sem_.Get(expr->index);
    auto* obj = sem_.Get(expr->object);
    auto* obj_raw_ty = obj->Type();
    auto* obj_ty = obj_raw_ty->UnwrapRef();
    auto* ty = Switch(
        obj_ty,  //
        [&](const sem::Array* arr) { return arr->ElemType(); },
        [&](const sem::Vector* vec) { return vec->type(); },
        [&](const sem::Matrix* mat) {
            return builder_->create<sem::Vector>(mat->type(), mat->rows());
        },
        [&](Default) {
            AddError("cannot index type '" + sem_.TypeNameOf(obj_ty) + "'", expr->source);
            return nullptr;
        });
    if (ty == nullptr) {
        return nullptr;
    }

    auto* idx_ty = idx->Type()->UnwrapRef();
    if (!idx_ty->IsAnyOf<sem::I32, sem::U32>()) {
        AddError("index must be of type 'i32' or 'u32', found: '" + sem_.TypeNameOf(idx_ty) + "'",
                 idx->Declaration()->source);
        return nullptr;
    }

    // If we're extracting from a reference, we return a reference.
    if (auto* ref = obj_raw_ty->As<sem::Reference>()) {
        ty = builder_->create<sem::Reference>(ty, ref->StorageClass(), ref->Access());
    }

    auto val = EvaluateConstantValue(expr, ty);
    bool has_side_effects = idx->HasSideEffects() || obj->HasSideEffects();
    auto* sem = builder_->create<sem::Expression>(expr, ty, current_statement_, val,
                                                  has_side_effects, obj->SourceVariable());
    sem->Behaviors() = idx->Behaviors() + obj->Behaviors();
    return sem;
}

sem::Expression* Resolver::Bitcast(const ast::BitcastExpression* expr) {
    auto* inner = sem_.Get(expr->expr);
    auto* ty = Type(expr->type);
    if (!ty) {
        return nullptr;
    }

    auto val = EvaluateConstantValue(expr, ty);
    auto* sem = builder_->create<sem::Expression>(expr, ty, current_statement_, val,
                                                  inner->HasSideEffects());

    sem->Behaviors() = inner->Behaviors();

    if (!validator_.Bitcast(expr, ty)) {
        return nullptr;
    }

    return sem;
}

sem::Call* Resolver::Call(const ast::CallExpression* expr) {
    std::vector<const sem::Expression*> args(expr->args.size());
    std::vector<const sem::Type*> arg_tys(args.size());
    sem::Behaviors arg_behaviors;

    // The element type of all the arguments. Nullptr if argument types are
    // different.
    const sem::Type* arg_el_ty = nullptr;

    for (size_t i = 0; i < expr->args.size(); i++) {
        auto* arg = sem_.Get(expr->args[i]);
        if (!arg) {
            return nullptr;
        }
        args[i] = arg;
        arg_tys[i] = args[i]->Type();
        arg_behaviors.Add(arg->Behaviors());

        // Determine the common argument element type
        auto* el_ty = arg_tys[i]->UnwrapRef();
        if (auto* vec = el_ty->As<sem::Vector>()) {
            el_ty = vec->type();
        } else if (auto* mat = el_ty->As<sem::Matrix>()) {
            el_ty = mat->type();
        }
        if (i == 0) {
            arg_el_ty = el_ty;
        } else if (arg_el_ty != el_ty) {
            arg_el_ty = nullptr;
        }
    }

    arg_behaviors.Remove(sem::Behavior::kNext);

    auto type_ctor_or_conv = [&](const sem::Type* ty) -> sem::Call* {
        // The call has resolved to a type constructor or cast.
        if (args.size() == 1) {
            auto* target = ty;
            auto* source = args[0]->Type()->UnwrapRef();
            if ((source != target) &&  //
                ((source->is_scalar() && target->is_scalar()) ||
                 (source->Is<sem::Vector>() && target->Is<sem::Vector>()) ||
                 (source->Is<sem::Matrix>() && target->Is<sem::Matrix>()))) {
                // Note: Matrix types currently cannot be converted (the element type
                // must only be f32). We implement this for the day we support other
                // matrix element types.
                return TypeConversion(expr, ty, args[0], arg_tys[0]);
            }
        }
        return TypeConstructor(expr, ty, std::move(args), std::move(arg_tys));
    };

    // Resolve the target of the CallExpression to determine whether this is a
    // function call, cast or type constructor expression.
    if (expr->target.type) {
        const sem::Type* ty = nullptr;

        auto err_cannot_infer_el_ty = [&](std::string name) {
            AddError("cannot infer " + name +
                         " element type, as constructor arguments have different types",
                     expr->source);
            for (size_t i = 0; i < args.size(); i++) {
                auto* arg = args[i];
                AddNote("argument " + std::to_string(i) + " has type " +
                            arg->Type()->FriendlyName(builder_->Symbols()),
                        arg->Declaration()->source);
            }
        };

        if (!expr->args.empty()) {
            // vecN() without explicit element type?
            // Try to infer element type from args
            if (auto* vec = expr->target.type->As<ast::Vector>()) {
                if (!vec->type) {
                    if (!arg_el_ty) {
                        err_cannot_infer_el_ty("vector");
                        return nullptr;
                    }

                    Mark(vec);
                    auto* v =
                        builder_->create<sem::Vector>(arg_el_ty, static_cast<uint32_t>(vec->width));
                    if (!validator_.Vector(v, vec->source)) {
                        return nullptr;
                    }
                    builder_->Sem().Add(vec, v);
                    ty = v;
                }
            }

            // matNxM() without explicit element type?
            // Try to infer element type from args
            if (auto* mat = expr->target.type->As<ast::Matrix>()) {
                if (!mat->type) {
                    if (!arg_el_ty) {
                        err_cannot_infer_el_ty("matrix");
                        return nullptr;
                    }

                    Mark(mat);
                    auto* column_type = builder_->create<sem::Vector>(arg_el_ty, mat->rows);
                    auto* m = builder_->create<sem::Matrix>(column_type, mat->columns);
                    if (!validator_.Matrix(m, mat->source)) {
                        return nullptr;
                    }
                    builder_->Sem().Add(mat, m);
                    ty = m;
                }
            }
        }

        if (ty == nullptr) {
            ty = Type(expr->target.type);
            if (!ty) {
                return nullptr;
            }
        }

        return type_ctor_or_conv(ty);
    }

    auto* ident = expr->target.name;
    Mark(ident);

    auto* resolved = sem_.ResolvedSymbol(ident);
    return Switch(
        resolved,  //
        [&](sem::Type* type) { return type_ctor_or_conv(type); },
        [&](sem::Function* func) {
            return FunctionCall(expr, func, std::move(args), arg_behaviors);
        },
        [&](sem::Variable* var) {
            auto name = builder_->Symbols().NameFor(var->Declaration()->symbol);
            AddError("cannot call variable '" + name + "'", ident->source);
            AddNote("'" + name + "' declared here", var->Declaration()->source);
            return nullptr;
        },
        [&](Default) -> sem::Call* {
            auto name = builder_->Symbols().NameFor(ident->symbol);
            auto builtin_type = sem::ParseBuiltinType(name);
            if (builtin_type != sem::BuiltinType::kNone) {
                return BuiltinCall(expr, builtin_type, std::move(args), std::move(arg_tys));
            }

            TINT_ICE(Resolver, diagnostics_)
                << expr->source << " unresolved CallExpression target:\n"
                << "resolved: " << (resolved ? resolved->TypeInfo().name : "<null>") << "\n"
                << "name: " << builder_->Symbols().NameFor(ident->symbol);
            return nullptr;
        });
}

sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
                                 sem::BuiltinType builtin_type,
                                 const std::vector<const sem::Expression*> args,
                                 const std::vector<const sem::Type*> arg_tys) {
    auto* builtin = intrinsic_table_->Lookup(builtin_type, std::move(arg_tys), expr->source);
    if (!builtin) {
        return nullptr;
    }

    if (builtin->IsDeprecated()) {
        AddWarning("use of deprecated builtin", expr->source);
    }

    bool has_side_effects =
        builtin->HasSideEffects() ||
        std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
    auto* call = builder_->create<sem::Call>(expr, builtin, std::move(args), current_statement_,
                                             sem::Constant{}, has_side_effects);

    current_function_->AddDirectlyCalledBuiltin(builtin);

    if (!validator_.RequiredExtensionForBuiltinFunction(call, builder_->AST().Extensions())) {
        return nullptr;
    }

    if (IsTextureBuiltin(builtin_type)) {
        if (!validator_.TextureBuiltinFunction(call)) {
            return nullptr;
        }
        // Collect a texture/sampler pair for this builtin.
        const auto& signature = builtin->Signature();
        int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
        if (texture_index == -1) {
            TINT_ICE(Resolver, diagnostics_) << "texture builtin without texture parameter";
        }

        auto* texture = args[texture_index]->As<sem::VariableUser>()->Variable();
        if (!texture->Type()->UnwrapRef()->Is<sem::StorageTexture>()) {
            int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler);
            const sem::Variable* sampler =
                sampler_index != -1 ? args[sampler_index]->As<sem::VariableUser>()->Variable()
                                    : nullptr;
            current_function_->AddTextureSamplerPair(texture, sampler);
        }
    }

    if (!validator_.BuiltinCall(call)) {
        return nullptr;
    }

    current_function_->AddDirectCall(call);

    return call;
}

sem::Call* Resolver::FunctionCall(const ast::CallExpression* expr,
                                  sem::Function* target,
                                  const std::vector<const sem::Expression*> args,
                                  sem::Behaviors arg_behaviors) {
    auto sym = expr->target.name->symbol;
    auto name = builder_->Symbols().NameFor(sym);

    // TODO(crbug.com/tint/1420): For now, assume all function calls have side
    // effects.
    bool has_side_effects = true;
    auto* call = builder_->create<sem::Call>(expr, target, std::move(args), current_statement_,
                                             sem::Constant{}, has_side_effects);

    if (current_function_) {
        // Note: Requires called functions to be resolved first.
        // This is currently guaranteed as functions must be declared before
        // use.
        current_function_->AddTransitivelyCalledFunction(target);
        current_function_->AddDirectCall(call);
        for (auto* transitive_call : target->TransitivelyCalledFunctions()) {
            current_function_->AddTransitivelyCalledFunction(transitive_call);
        }

        // We inherit any referenced variables from the callee.
        for (auto* var : target->TransitivelyReferencedGlobals()) {
            current_function_->AddTransitivelyReferencedGlobal(var);
        }

        // Map all texture/sampler pairs from the target function to the
        // current function. These can only be global or parameter
        // variables. Resolve any parameter variables to the corresponding
        // argument passed to the current function. Leave global variables
        // as-is. Then add the mapped pair to the current function's list of
        // texture/sampler pairs.
        for (sem::VariablePair pair : target->TextureSamplerPairs()) {
            const sem::Variable* texture = pair.first;
            const sem::Variable* sampler = pair.second;
            if (auto* param = texture->As<sem::Parameter>()) {
                texture = args[param->Index()]->As<sem::VariableUser>()->Variable();
            }
            if (sampler) {
                if (auto* param = sampler->As<sem::Parameter>()) {
                    sampler = args[param->Index()]->As<sem::VariableUser>()->Variable();
                }
            }
            current_function_->AddTextureSamplerPair(texture, sampler);
        }
    }

    target->AddCallSite(call);

    call->Behaviors() = arg_behaviors + target->Behaviors();

    if (!validator_.FunctionCall(call, current_statement_)) {
        return nullptr;
    }

    return call;
}

sem::Call* Resolver::TypeConversion(const ast::CallExpression* expr,
                                    const sem::Type* target,
                                    const sem::Expression* arg,
                                    const sem::Type* source) {
    // It is not valid to have a type-cast call expression inside a call
    // statement.
    if (IsCallStatement(expr)) {
        AddError("type cast evaluated but not used", expr->source);
        return nullptr;
    }

    auto* call_target = utils::GetOrCreate(
        type_conversions_, TypeConversionSig{target, source}, [&]() -> sem::TypeConversion* {
            // Now that the argument types have been determined, make sure that
            // they obey the conversion rules laid out in
            // https://gpuweb.github.io/gpuweb/wgsl/#conversion-expr.
            bool ok = Switch(
                target,
                [&](const sem::Vector* vec_type) {
                    return validator_.VectorConstructorOrCast(expr, vec_type);
                },
                [&](const sem::Matrix* mat_type) {
                    // Note: Matrix types currently cannot be converted (the element
                    // type must only be f32). We implement this for the day we
                    // support other matrix element types.
                    return validator_.MatrixConstructorOrCast(expr, mat_type);
                },
                [&](const sem::Array* arr_type) {
                    return validator_.ArrayConstructorOrCast(expr, arr_type);
                },
                [&](const sem::Struct* struct_type) {
                    return validator_.StructureConstructorOrCast(expr, struct_type);
                },
                [&](Default) {
                    if (target->is_scalar()) {
                        return validator_.ScalarConstructorOrCast(expr, target);
                    }
                    AddError("type is not constructible", expr->source);
                    return false;
                });
            if (!ok) {
                return nullptr;
            }

            auto* param =
                builder_->create<sem::Parameter>(nullptr,                   // declaration
                                                 0,                         // index
                                                 source->UnwrapRef(),       // type
                                                 ast::StorageClass::kNone,  // storage_class
                                                 ast::Access::kUndefined);  // access
            return builder_->create<sem::TypeConversion>(target, param);
        });

    if (!call_target) {
        return nullptr;
    }

    auto val = EvaluateConstantValue(expr, target);
    bool has_side_effects = arg->HasSideEffects();
    return builder_->create<sem::Call>(expr, call_target, std::vector<const sem::Expression*>{arg},
                                       current_statement_, val, has_side_effects);
}

sem::Call* Resolver::TypeConstructor(const ast::CallExpression* expr,
                                     const sem::Type* ty,
                                     const std::vector<const sem::Expression*> args,
                                     const std::vector<const sem::Type*> arg_tys) {
    // It is not valid to have a type-constructor call expression as a call
    // statement.
    if (IsCallStatement(expr)) {
        AddError("type constructor evaluated but not used", expr->source);
        return nullptr;
    }

    auto* call_target = utils::GetOrCreate(
        type_ctors_, TypeConstructorSig{ty, arg_tys}, [&]() -> sem::TypeConstructor* {
            // Now that the argument types have been determined, make sure that
            // they obey the constructor type rules laid out in
            // https://gpuweb.github.io/gpuweb/wgsl/#type-constructor-expr.
            bool ok = Switch(
                ty,
                [&](const sem::Vector* vec_type) {
                    return validator_.VectorConstructorOrCast(expr, vec_type);
                },
                [&](const sem::Matrix* mat_type) {
                    return validator_.MatrixConstructorOrCast(expr, mat_type);
                },
                [&](const sem::Array* arr_type) {
                    return validator_.ArrayConstructorOrCast(expr, arr_type);
                },
                [&](const sem::Struct* struct_type) {
                    return validator_.StructureConstructorOrCast(expr, struct_type);
                },
                [&](Default) {
                    if (ty->is_scalar()) {
                        return validator_.ScalarConstructorOrCast(expr, ty);
                    }
                    AddError("type is not constructible", expr->source);
                    return false;
                });
            if (!ok) {
                return nullptr;
            }

            return builder_->create<sem::TypeConstructor>(
                ty, utils::Transform(arg_tys,
                                     [&](const sem::Type* t, size_t i) -> const sem::Parameter* {
                                         return builder_->create<sem::Parameter>(
                                             nullptr,                   // declaration
                                             static_cast<uint32_t>(i),  // index
                                             t->UnwrapRef(),            // type
                                             ast::StorageClass::kNone,  // storage_class
                                             ast::Access::kUndefined);  // access
                                     }));
        });

    if (!call_target) {
        return nullptr;
    }

    auto val = EvaluateConstantValue(expr, ty);
    bool has_side_effects =
        std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
    return builder_->create<sem::Call>(expr, call_target, std::move(args), current_statement_, val,
                                       has_side_effects);
}

sem::Expression* Resolver::Literal(const ast::LiteralExpression* literal) {
    auto* ty = Switch(
        literal,
        [&](const ast::IntLiteralExpression* i) -> sem::Type* {
            switch (i->suffix) {
                case ast::IntLiteralExpression::Suffix::kNone:
                // TODO(crbug.com/tint/1504): This will need to become abstract-int.
                // For now, treat as 'i32'.
                case ast::IntLiteralExpression::Suffix::kI:
                    return builder_->create<sem::I32>();
                case ast::IntLiteralExpression::Suffix::kU:
                    return builder_->create<sem::U32>();
            }
            return nullptr;
        },
        [&](const ast::FloatLiteralExpression*) { return builder_->create<sem::F32>(); },
        [&](const ast::BoolLiteralExpression*) { return builder_->create<sem::Bool>(); },
        [&](Default) { return nullptr; });

    if (ty == nullptr) {
        TINT_UNREACHABLE(Resolver, builder_->Diagnostics())
            << "Unhandled literal type: " << literal->TypeInfo().name;
        return nullptr;
    }

    auto val = EvaluateConstantValue(literal, ty);
    return builder_->create<sem::Expression>(literal, ty, current_statement_, val,
                                             /* has_side_effects */ false);
}

sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
    auto symbol = expr->symbol;
    auto* resolved = sem_.ResolvedSymbol(expr);
    if (auto* var = As<sem::Variable>(resolved)) {
        auto* user = builder_->create<sem::VariableUser>(expr, current_statement_, var);

        if (current_statement_) {
            // If identifier is part of a loop continuing block, make sure it
            // doesn't refer to a variable that is bypassed by a continue statement
            // in the loop's body block.
            if (auto* continuing_block =
                    current_statement_->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
                auto* loop_block = continuing_block->FindFirstParent<sem::LoopBlockStatement>();
                if (loop_block->FirstContinue()) {
                    auto& decls = loop_block->Decls();
                    // If our identifier is in loop_block->decls, make sure its index is
                    // less than first_continue
                    auto iter = std::find_if(decls.begin(), decls.end(),
                                             [&symbol](auto* v) { return v->symbol == symbol; });
                    if (iter != decls.end()) {
                        auto var_decl_index =
                            static_cast<size_t>(std::distance(decls.begin(), iter));
                        if (var_decl_index >= loop_block->NumDeclsAtFirstContinue()) {
                            AddError("continue statement bypasses declaration of '" +
                                         builder_->Symbols().NameFor(symbol) + "'",
                                     loop_block->FirstContinue()->source);
                            AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
                                        "' declared here",
                                    (*iter)->source);
                            AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
                                        "' referenced in continuing block here",
                                    expr->source);
                            return nullptr;
                        }
                    }
                }
            }
        }

        if (current_function_) {
            if (auto* global = var->As<sem::GlobalVariable>()) {
                current_function_->AddDirectlyReferencedGlobal(global);
            }
        }

        var->AddUser(user);
        return user;
    }

    if (Is<sem::Function>(resolved)) {
        AddError("missing '(' for function call", expr->source.End());
        return nullptr;
    }

    if (IsBuiltin(symbol)) {
        AddError("missing '(' for builtin call", expr->source.End());
        return nullptr;
    }

    if (resolved->Is<sem::Type>()) {
        AddError("missing '(' for type constructor or cast", expr->source.End());
        return nullptr;
    }

    TINT_ICE(Resolver, diagnostics_)
        << expr->source << " unresolved identifier:\n"
        << "resolved: " << (resolved ? resolved->TypeInfo().name : "<null>") << "\n"
        << "name: " << builder_->Symbols().NameFor(symbol);
    return nullptr;
}

sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* expr) {
    auto* structure = sem_.TypeOf(expr->structure);
    auto* storage_ty = structure->UnwrapRef();
    auto* source_var = sem_.Get(expr->structure)->SourceVariable();

    const sem::Type* ret = nullptr;
    std::vector<uint32_t> swizzle;

    // Structure may be a side-effecting expression (e.g. function call).
    auto* sem_structure = sem_.Get(expr->structure);
    bool has_side_effects = sem_structure && sem_structure->HasSideEffects();

    if (auto* str = storage_ty->As<sem::Struct>()) {
        Mark(expr->member);
        auto symbol = expr->member->symbol;

        const sem::StructMember* member = nullptr;
        for (auto* m : str->Members()) {
            if (m->Name() == symbol) {
                ret = m->Type();
                member = m;
                break;
            }
        }

        if (ret == nullptr) {
            AddError("struct member " + builder_->Symbols().NameFor(symbol) + " not found",
                     expr->source);
            return nullptr;
        }

        // If we're extracting from a reference, we return a reference.
        if (auto* ref = structure->As<sem::Reference>()) {
            ret = builder_->create<sem::Reference>(ret, ref->StorageClass(), ref->Access());
        }

        return builder_->create<sem::StructMemberAccess>(expr, ret, current_statement_, member,
                                                         has_side_effects, source_var);
    }

    if (auto* vec = storage_ty->As<sem::Vector>()) {
        Mark(expr->member);
        std::string s = builder_->Symbols().NameFor(expr->member->symbol);
        auto size = s.size();
        swizzle.reserve(s.size());

        for (auto c : s) {
            switch (c) {
                case 'x':
                case 'r':
                    swizzle.emplace_back(0);
                    break;
                case 'y':
                case 'g':
                    swizzle.emplace_back(1);
                    break;
                case 'z':
                case 'b':
                    swizzle.emplace_back(2);
                    break;
                case 'w':
                case 'a':
                    swizzle.emplace_back(3);
                    break;
                default:
                    AddError("invalid vector swizzle character",
                             expr->member->source.Begin() + swizzle.size());
                    return nullptr;
            }

            if (swizzle.back() >= vec->Width()) {
                AddError("invalid vector swizzle member", expr->member->source);
                return nullptr;
            }
        }

        if (size < 1 || size > 4) {
            AddError("invalid vector swizzle size", expr->member->source);
            return nullptr;
        }

        // All characters are valid, check if they're being mixed
        auto is_rgba = [](char c) { return c == 'r' || c == 'g' || c == 'b' || c == 'a'; };
        auto is_xyzw = [](char c) { return c == 'x' || c == 'y' || c == 'z' || c == 'w'; };
        if (!std::all_of(s.begin(), s.end(), is_rgba) &&
            !std::all_of(s.begin(), s.end(), is_xyzw)) {
            AddError("invalid mixing of vector swizzle characters rgba with xyzw",
                     expr->member->source);
            return nullptr;
        }

        if (size == 1) {
            // A single element swizzle is just the type of the vector.
            ret = vec->type();
            // If we're extracting from a reference, we return a reference.
            if (auto* ref = structure->As<sem::Reference>()) {
                ret = builder_->create<sem::Reference>(ret, ref->StorageClass(), ref->Access());
            }
        } else {
            // The vector will have a number of components equal to the length of
            // the swizzle.
            ret = builder_->create<sem::Vector>(vec->type(), static_cast<uint32_t>(size));
        }
        return builder_->create<sem::Swizzle>(expr, ret, current_statement_, std::move(swizzle),
                                              has_side_effects, source_var);
    }

    AddError("invalid member accessor expression. Expected vector or struct, got '" +
                 sem_.TypeNameOf(storage_ty) + "'",
             expr->structure->source);
    return nullptr;
}

sem::Expression* Resolver::Binary(const ast::BinaryExpression* expr) {
    auto* lhs = sem_.Get(expr->lhs);
    auto* rhs = sem_.Get(expr->rhs);
    auto* lhs_ty = lhs->Type()->UnwrapRef();
    auto* rhs_ty = rhs->Type()->UnwrapRef();

    auto* ty = intrinsic_table_->Lookup(expr->op, lhs_ty, rhs_ty, expr->source, false).result;
    if (!ty) {
        return nullptr;
    }

    auto val = EvaluateConstantValue(expr, ty);
    bool has_side_effects = lhs->HasSideEffects() || rhs->HasSideEffects();
    auto* sem =
        builder_->create<sem::Expression>(expr, ty, current_statement_, val, has_side_effects);
    sem->Behaviors() = lhs->Behaviors() + rhs->Behaviors();

    return sem;
}

sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
    auto* expr = sem_.Get(unary->expr);
    auto* expr_ty = expr->Type();
    if (!expr_ty) {
        return nullptr;
    }

    const sem::Type* ty = nullptr;
    const sem::Variable* source_var = nullptr;

    switch (unary->op) {
        case ast::UnaryOp::kAddressOf:
            if (auto* ref = expr_ty->As<sem::Reference>()) {
                if (ref->StoreType()->UnwrapRef()->is_handle()) {
                    AddError("cannot take the address of expression in handle storage class",
                             unary->expr->source);
                    return nullptr;
                }

                auto* array = unary->expr->As<ast::IndexAccessorExpression>();
                auto* member = unary->expr->As<ast::MemberAccessorExpression>();
                if ((array && sem_.TypeOf(array->object)->UnwrapRef()->Is<sem::Vector>()) ||
                    (member && sem_.TypeOf(member->structure)->UnwrapRef()->Is<sem::Vector>())) {
                    AddError("cannot take the address of a vector component", unary->expr->source);
                    return nullptr;
                }

                ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->StorageClass(),
                                                    ref->Access());

                source_var = expr->SourceVariable();
            } else {
                AddError("cannot take the address of expression", unary->expr->source);
                return nullptr;
            }
            break;

        case ast::UnaryOp::kIndirection:
            if (auto* ptr = expr_ty->As<sem::Pointer>()) {
                ty = builder_->create<sem::Reference>(ptr->StoreType(), ptr->StorageClass(),
                                                      ptr->Access());
                source_var = expr->SourceVariable();
            } else {
                AddError("cannot dereference expression of type '" + sem_.TypeNameOf(expr_ty) + "'",
                         unary->expr->source);
                return nullptr;
            }
            break;

        default: {
            ty = intrinsic_table_->Lookup(unary->op, expr_ty, unary->source).result;
            if (!ty) {
                return nullptr;
            }
        }
    }

    auto val = EvaluateConstantValue(unary, ty);
    auto* sem = builder_->create<sem::Expression>(unary, ty, current_statement_, val,
                                                  expr->HasSideEffects(), source_var);
    sem->Behaviors() = expr->Behaviors();
    return sem;
}

sem::Type* Resolver::TypeDecl(const ast::TypeDecl* named_type) {
    sem::Type* result = nullptr;
    if (auto* alias = named_type->As<ast::Alias>()) {
        result = Alias(alias);
    } else if (auto* str = named_type->As<ast::Struct>()) {
        result = Structure(str);
    } else {
        TINT_UNREACHABLE(Resolver, diagnostics_) << "Unhandled TypeDecl";
    }

    if (!result) {
        return nullptr;
    }

    builder_->Sem().Add(named_type, result);
    return result;
}

sem::Array* Resolver::Array(const ast::Array* arr) {
    auto source = arr->source;

    auto* elem_type = Type(arr->type);
    if (!elem_type) {
        return nullptr;
    }

    if (!validator_.IsPlain(elem_type)) {  // Check must come before GetDefaultAlignAndSize()
        AddError(sem_.TypeNameOf(elem_type) + " cannot be used as an element type of an array",
                 source);
        return nullptr;
    }

    uint32_t el_align = elem_type->Align();
    uint32_t el_size = elem_type->Size();

    if (!validator_.NoDuplicateAttributes(arr->attributes)) {
        return nullptr;
    }

    // Look for explicit stride via @stride(n) attribute
    uint32_t explicit_stride = 0;
    for (auto* attr : arr->attributes) {
        Mark(attr);
        if (auto* sd = attr->As<ast::StrideAttribute>()) {
            explicit_stride = sd->stride;
            if (!validator_.ArrayStrideAttribute(sd, el_size, el_align, source)) {
                return nullptr;
            }
            continue;
        }

        AddError("attribute is not valid for array types", attr->source);
        return nullptr;
    }

    // Calculate implicit stride
    uint64_t implicit_stride = utils::RoundUp<uint64_t>(el_align, el_size);

    uint64_t stride = explicit_stride ? explicit_stride : implicit_stride;

    // Evaluate the constant array size expression.
    // sem::Array uses a size of 0 for a runtime-sized array.
    uint32_t count = 0;
    if (auto* count_expr = arr->count) {
        auto* count_sem = Expression(count_expr);
        if (!count_sem) {
            return nullptr;
        }

        auto size_source = count_expr->source;

        auto* ty = count_sem->Type()->UnwrapRef();
        if (!ty->is_integer_scalar()) {
            AddError("array size must be integer scalar", size_source);
            return nullptr;
        }

        if (auto* ident = count_expr->As<ast::IdentifierExpression>()) {
            // Make sure the identifier is a non-overridable module-scope constant.
            auto* var = sem_.ResolvedSymbol<sem::GlobalVariable>(ident);
            if (!var || !var->Declaration()->is_const) {
                AddError("array size identifier must be a module-scope constant", size_source);
                return nullptr;
            }
            if (var->IsOverridable()) {
                AddError("array size expression must not be pipeline-overridable", size_source);
                return nullptr;
            }

            count_expr = var->Declaration()->constructor;
        } else if (!count_expr->Is<ast::LiteralExpression>()) {
            AddError(
                "array size expression must be either a literal or a module-scope "
                "constant",
                size_source);
            return nullptr;
        }

        auto count_val = count_sem->ConstantValue();
        if (!count_val) {
            TINT_ICE(Resolver, diagnostics_) << "could not resolve array size expression";
            return nullptr;
        }

        if (ty->is_signed_integer_scalar() ? count_val.Elements()[0].i32 < 1
                                           : count_val.Elements()[0].u32 < 1u) {
            AddError("array size must be at least 1", size_source);
            return nullptr;
        }

        count = count_val.Elements()[0].u32;
    }

    auto size = std::max<uint64_t>(count, 1) * stride;
    if (size > std::numeric_limits<uint32_t>::max()) {
        std::stringstream msg;
        msg << "array size in bytes must not exceed 0x" << std::hex
            << std::numeric_limits<uint32_t>::max() << ", but is 0x" << std::hex << size;
        AddError(msg.str(), arr->source);
        return nullptr;
    }
    if (stride > std::numeric_limits<uint32_t>::max() ||
        implicit_stride > std::numeric_limits<uint32_t>::max()) {
        TINT_ICE(Resolver, diagnostics_) << "calculated array stride exceeds uint32";
        return nullptr;
    }
    auto* out = builder_->create<sem::Array>(
        elem_type, count, el_align, static_cast<uint32_t>(size), static_cast<uint32_t>(stride),
        static_cast<uint32_t>(implicit_stride));

    if (!validator_.Array(out, source)) {
        return nullptr;
    }

    if (elem_type->Is<sem::Atomic>()) {
        atomic_composite_info_.emplace(out, arr->type->source);
    } else {
        auto found = atomic_composite_info_.find(elem_type);
        if (found != atomic_composite_info_.end()) {
            atomic_composite_info_.emplace(out, found->second);
        }
    }

    return out;
}

sem::Type* Resolver::Alias(const ast::Alias* alias) {
    auto* ty = Type(alias->type);
    if (!ty) {
        return nullptr;
    }
    if (!validator_.Alias(alias)) {
        return nullptr;
    }
    return ty;
}

sem::Struct* Resolver::Structure(const ast::Struct* str) {
    if (!validator_.NoDuplicateAttributes(str->attributes)) {
        return nullptr;
    }
    for (auto* attr : str->attributes) {
        Mark(attr);
    }

    sem::StructMemberList sem_members;
    sem_members.reserve(str->members.size());

    // Calculate the effective size and alignment of each field, and the overall
    // size of the structure.
    // For size, use the size attribute if provided, otherwise use the default
    // size for the type.
    // For alignment, use the alignment attribute if provided, otherwise use the
    // default alignment for the member type.
    // Diagnostic errors are raised if a basic rule is violated.
    // Validation of storage-class rules requires analysing the actual variable
    // usage of the structure, and so is performed as part of the variable
    // validation.
    uint64_t struct_size = 0;
    uint64_t struct_align = 1;
    std::unordered_map<Symbol, const ast::StructMember*> member_map;

    for (auto* member : str->members) {
        Mark(member);
        auto result = member_map.emplace(member->symbol, member);
        if (!result.second) {
            AddError("redefinition of '" + builder_->Symbols().NameFor(member->symbol) + "'",
                     member->source);
            AddNote("previous definition is here", result.first->second->source);
            return nullptr;
        }

        // Resolve member type
        auto* type = Type(member->type);
        if (!type) {
            return nullptr;
        }

        // validator_.Validate member type
        if (!validator_.IsPlain(type)) {
            AddError(sem_.TypeNameOf(type) + " cannot be used as the type of a structure member",
                     member->source);
            return nullptr;
        }

        uint64_t offset = struct_size;
        uint64_t align = type->Align();
        uint64_t size = type->Size();

        if (!validator_.NoDuplicateAttributes(member->attributes)) {
            return nullptr;
        }

        bool has_offset_attr = false;
        bool has_align_attr = false;
        bool has_size_attr = false;
        for (auto* attr : member->attributes) {
            Mark(attr);
            if (auto* o = attr->As<ast::StructMemberOffsetAttribute>()) {
                // Offset attributes are not part of the WGSL spec, but are emitted
                // by the SPIR-V reader.
                if (o->offset < struct_size) {
                    AddError("offsets must be in ascending order", o->source);
                    return nullptr;
                }
                offset = o->offset;
                align = 1;
                has_offset_attr = true;
            } else if (auto* a = attr->As<ast::StructMemberAlignAttribute>()) {
                if (a->align <= 0 || !utils::IsPowerOfTwo(a->align)) {
                    AddError("align value must be a positive, power-of-two integer", a->source);
                    return nullptr;
                }
                align = a->align;
                has_align_attr = true;
            } else if (auto* s = attr->As<ast::StructMemberSizeAttribute>()) {
                if (s->size < size) {
                    AddError("size must be at least as big as the type's size (" +
                                 std::to_string(size) + ")",
                             s->source);
                    return nullptr;
                }
                size = s->size;
                has_size_attr = true;
            }
        }

        if (has_offset_attr && (has_align_attr || has_size_attr)) {
            AddError("offset attributes cannot be used with align or size attributes",
                     member->source);
            return nullptr;
        }

        offset = utils::RoundUp(align, offset);
        if (offset > std::numeric_limits<uint32_t>::max()) {
            std::stringstream msg;
            msg << "struct member has byte offset 0x" << std::hex << offset
                << ", but must not exceed 0x" << std::hex << std::numeric_limits<uint32_t>::max();
            AddError(msg.str(), member->source);
            return nullptr;
        }

        auto* sem_member = builder_->create<sem::StructMember>(
            member, member->symbol, type, static_cast<uint32_t>(sem_members.size()),
            static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
            static_cast<uint32_t>(size));
        builder_->Sem().Add(member, sem_member);
        sem_members.emplace_back(sem_member);

        struct_size = offset + size;
        struct_align = std::max(struct_align, align);
    }

    uint64_t size_no_padding = struct_size;
    struct_size = utils::RoundUp(struct_align, struct_size);

    if (struct_size > std::numeric_limits<uint32_t>::max()) {
        std::stringstream msg;
        msg << "struct size in bytes must not exceed 0x" << std::hex
            << std::numeric_limits<uint32_t>::max() << ", but is 0x" << std::hex << struct_size;
        AddError(msg.str(), str->source);
        return nullptr;
    }
    if (struct_align > std::numeric_limits<uint32_t>::max()) {
        TINT_ICE(Resolver, diagnostics_) << "calculated struct stride exceeds uint32";
        return nullptr;
    }

    auto* out = builder_->create<sem::Struct>(
        str, str->name, sem_members, static_cast<uint32_t>(struct_align),
        static_cast<uint32_t>(struct_size), static_cast<uint32_t>(size_no_padding));

    for (size_t i = 0; i < sem_members.size(); i++) {
        auto* mem_type = sem_members[i]->Type();
        if (mem_type->Is<sem::Atomic>()) {
            atomic_composite_info_.emplace(out, sem_members[i]->Declaration()->source);
            break;
        } else {
            auto found = atomic_composite_info_.find(mem_type);
            if (found != atomic_composite_info_.end()) {
                atomic_composite_info_.emplace(out, found->second);
                break;
            }
        }
    }

    auto stage = current_function_ ? current_function_->Declaration()->PipelineStage()
                                   : ast::PipelineStage::kNone;
    if (!validator_.Structure(out, stage)) {
        return nullptr;
    }

    return out;
}

sem::Statement* Resolver::ReturnStatement(const ast::ReturnStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        auto& behaviors = current_statement_->Behaviors();
        behaviors = sem::Behavior::kReturn;

        if (auto* value = stmt->value) {
            auto* expr = Expression(value);
            if (!expr) {
                return false;
            }
            behaviors.Add(expr->Behaviors() - sem::Behavior::kNext);
        }

        // Validate after processing the return value expression so that its type
        // is available for validation.
        auto* ret_type =
            stmt->value ? sem_.TypeOf(stmt->value)->UnwrapRef() : builder_->create<sem::Void>();
        return validator_.Return(stmt, current_function_->ReturnType(), ret_type,
                                 current_statement_);
    });
}

sem::SwitchStatement* Resolver::SwitchStatement(const ast::SwitchStatement* stmt) {
    auto* sem = builder_->create<sem::SwitchStatement>(stmt, current_compound_statement_,
                                                       current_function_);
    return StatementScope(stmt, sem, [&] {
        auto& behaviors = sem->Behaviors();

        auto* cond = Expression(stmt->condition);
        if (!cond) {
            return false;
        }
        behaviors = cond->Behaviors() - sem::Behavior::kNext;

        for (auto* case_stmt : stmt->body) {
            Mark(case_stmt);
            auto* c = CaseStatement(case_stmt);
            if (!c) {
                return false;
            }
            behaviors.Add(c->Behaviors());
        }

        if (behaviors.Contains(sem::Behavior::kBreak)) {
            behaviors.Add(sem::Behavior::kNext);
        }
        behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kFallthrough);

        return validator_.SwitchStatement(stmt);
    });
}

sem::Statement* Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        Mark(stmt->variable);

        auto* var = Variable(stmt->variable, VariableKind::kLocal);
        if (!var) {
            return false;
        }

        for (auto* attr : stmt->variable->attributes) {
            Mark(attr);
            if (!attr->Is<ast::InternalAttribute>()) {
                AddError("attributes are not valid on local variables", attr->source);
                return false;
            }
        }

        if (current_block_) {  // Not all statements are inside a block
            current_block_->AddDecl(stmt->variable);
        }

        if (auto* ctor = var->Constructor()) {
            sem->Behaviors() = ctor->Behaviors();
        }

        return validator_.Variable(var);
    });
}

sem::Statement* Resolver::AssignmentStatement(const ast::AssignmentStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        auto* lhs = Expression(stmt->lhs);
        if (!lhs) {
            return false;
        }

        auto* rhs = Expression(stmt->rhs);
        if (!rhs) {
            return false;
        }

        auto& behaviors = sem->Behaviors();
        behaviors = rhs->Behaviors();
        if (!stmt->lhs->Is<ast::PhonyExpression>()) {
            behaviors.Add(lhs->Behaviors());
        }

        return validator_.Assignment(stmt, sem_.TypeOf(stmt->rhs));
    });
}

sem::Statement* Resolver::BreakStatement(const ast::BreakStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        sem->Behaviors() = sem::Behavior::kBreak;

        return validator_.BreakStatement(sem, current_statement_);
    });
}

sem::Statement* Resolver::CallStatement(const ast::CallStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        if (auto* expr = Expression(stmt->expr)) {
            sem->Behaviors() = expr->Behaviors();
            return true;
        }
        return false;
    });
}

sem::Statement* Resolver::CompoundAssignmentStatement(
    const ast::CompoundAssignmentStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        auto* lhs = Expression(stmt->lhs);
        if (!lhs) {
            return false;
        }

        auto* rhs = Expression(stmt->rhs);
        if (!rhs) {
            return false;
        }

        sem->Behaviors() = rhs->Behaviors() + lhs->Behaviors();

        auto* lhs_ty = lhs->Type()->UnwrapRef();
        auto* rhs_ty = rhs->Type()->UnwrapRef();
        auto* ty = intrinsic_table_->Lookup(stmt->op, lhs_ty, rhs_ty, stmt->source, true).result;
        if (!ty) {
            return false;
        }
        return validator_.Assignment(stmt, ty);
    });
}

sem::Statement* Resolver::ContinueStatement(const ast::ContinueStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        sem->Behaviors() = sem::Behavior::kContinue;

        // Set if we've hit the first continue statement in our parent loop
        if (auto* block = sem->FindFirstParent<sem::LoopBlockStatement>()) {
            if (!block->FirstContinue()) {
                const_cast<sem::LoopBlockStatement*>(block)->SetFirstContinue(
                    stmt, block->Decls().size());
            }
        }

        return validator_.ContinueStatement(sem, current_statement_);
    });
}

sem::Statement* Resolver::DiscardStatement(const ast::DiscardStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        sem->Behaviors() = sem::Behavior::kDiscard;
        current_function_->SetHasDiscard();

        return validator_.DiscardStatement(sem, current_statement_);
    });
}

sem::Statement* Resolver::FallthroughStatement(const ast::FallthroughStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        sem->Behaviors() = sem::Behavior::kFallthrough;

        return validator_.FallthroughStatement(sem);
    });
}

sem::Statement* Resolver::IncrementDecrementStatement(
    const ast::IncrementDecrementStatement* stmt) {
    auto* sem =
        builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
    return StatementScope(stmt, sem, [&] {
        auto* lhs = Expression(stmt->lhs);
        if (!lhs) {
            return false;
        }
        sem->Behaviors() = lhs->Behaviors();

        return validator_.IncrementDecrementStatement(stmt);
    });
}

bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc,
                                            sem::Type* ty,
                                            const Source& usage) {
    ty = const_cast<sem::Type*>(ty->UnwrapRef());

    if (auto* str = ty->As<sem::Struct>()) {
        if (str->StorageClassUsage().count(sc)) {
            return true;  // Already applied
        }

        str->AddUsage(sc);

        for (auto* member : str->Members()) {
            if (!ApplyStorageClassUsageToType(sc, member->Type(), usage)) {
                std::stringstream err;
                err << "while analysing structure member " << sem_.TypeNameOf(str) << "."
                    << builder_->Symbols().NameFor(member->Declaration()->symbol);
                AddNote(err.str(), member->Declaration()->source);
                return false;
            }
        }
        return true;
    }

    if (auto* arr = ty->As<sem::Array>()) {
        if (arr->IsRuntimeSized() && sc != ast::StorageClass::kStorage) {
            AddError(
                "runtime-sized arrays can only be used in the <storage> storage "
                "class",
                usage);
            return false;
        }

        return ApplyStorageClassUsageToType(sc, const_cast<sem::Type*>(arr->ElemType()), usage);
    }

    if (ast::IsHostShareable(sc) && !validator_.IsHostShareable(ty)) {
        std::stringstream err;
        err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in storage class '" << sc
            << "' as it is non-host-shareable";
        AddError(err.str(), usage);
        return false;
    }

    return true;
}

template <typename SEM, typename F>
SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback) {
    builder_->Sem().Add(ast, sem);

    auto* as_compound = As<sem::CompoundStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);
    auto* as_block = As<sem::BlockStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);

    TINT_SCOPED_ASSIGNMENT(current_statement_, sem);
    TINT_SCOPED_ASSIGNMENT(current_compound_statement_,
                           as_compound ? as_compound : current_compound_statement_);
    TINT_SCOPED_ASSIGNMENT(current_block_, as_block ? as_block : current_block_);

    if (!callback()) {
        return nullptr;
    }

    return sem;
}

bool Resolver::Mark(const ast::Node* node) {
    if (node == nullptr) {
        TINT_ICE(Resolver, diagnostics_) << "Resolver::Mark() called with nullptr";
        return false;
    }
    if (marked_.emplace(node).second) {
        return true;
    }
    TINT_ICE(Resolver, diagnostics_) << "AST node '" << node->TypeInfo().name
                                     << "' was encountered twice in the same AST of a Program\n"
                                     << "At: " << node->source << "\n"
                                     << "Pointer: " << node;
    return false;
}

void Resolver::AddError(const std::string& msg, const Source& source) const {
    diagnostics_.add_error(diag::System::Resolver, msg, source);
}

void Resolver::AddWarning(const std::string& msg, const Source& source) const {
    diagnostics_.add_warning(diag::System::Resolver, msg, source);
}

void Resolver::AddNote(const std::string& msg, const Source& source) const {
    diagnostics_.add_note(diag::System::Resolver, msg, source);
}

bool Resolver::IsBuiltin(Symbol symbol) const {
    std::string name = builder_->Symbols().NameFor(symbol);
    return sem::ParseBuiltinType(name) != sem::BuiltinType::kNone;
}

bool Resolver::IsCallStatement(const ast::Expression* expr) const {
    return current_statement_ &&
           Is<ast::CallStatement>(current_statement_->Declaration(),
                                  [&](auto* stmt) { return stmt->expr == expr; });
}

////////////////////////////////////////////////////////////////////////////////
// Resolver::TypeConversionSig
////////////////////////////////////////////////////////////////////////////////
bool Resolver::TypeConversionSig::operator==(const TypeConversionSig& rhs) const {
    return target == rhs.target && source == rhs.source;
}
std::size_t Resolver::TypeConversionSig::Hasher::operator()(const TypeConversionSig& sig) const {
    return utils::Hash(sig.target, sig.source);
}

////////////////////////////////////////////////////////////////////////////////
// Resolver::TypeConstructorSig
////////////////////////////////////////////////////////////////////////////////
Resolver::TypeConstructorSig::TypeConstructorSig(const sem::Type* ty,
                                                 const std::vector<const sem::Type*> params)
    : type(ty), parameters(params) {}
Resolver::TypeConstructorSig::TypeConstructorSig(const TypeConstructorSig&) = default;
Resolver::TypeConstructorSig::~TypeConstructorSig() = default;

bool Resolver::TypeConstructorSig::operator==(const TypeConstructorSig& rhs) const {
    return type == rhs.type && parameters == rhs.parameters;
}
std::size_t Resolver::TypeConstructorSig::Hasher::operator()(const TypeConstructorSig& sig) const {
    return utils::Hash(sig.type, sig.parameters);
}

}  // namespace tint::resolver
