// 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/resolver/resolver.h"

#include <algorithm>
#include <utility>

#include "src/ast/alias.h"
#include "src/ast/array.h"
#include "src/ast/assignment_statement.h"
#include "src/ast/bitcast_expression.h"
#include "src/ast/break_statement.h"
#include "src/ast/call_statement.h"
#include "src/ast/continue_statement.h"
#include "src/ast/depth_texture.h"
#include "src/ast/disable_validation_decoration.h"
#include "src/ast/discard_statement.h"
#include "src/ast/fallthrough_statement.h"
#include "src/ast/if_statement.h"
#include "src/ast/internal_decoration.h"
#include "src/ast/interpolate_decoration.h"
#include "src/ast/loop_statement.h"
#include "src/ast/matrix.h"
#include "src/ast/override_decoration.h"
#include "src/ast/pointer.h"
#include "src/ast/return_statement.h"
#include "src/ast/sampled_texture.h"
#include "src/ast/sampler.h"
#include "src/ast/storage_texture.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/switch_statement.h"
#include "src/ast/type_name.h"
#include "src/ast/unary_op_expression.h"
#include "src/ast/variable_decl_statement.h"
#include "src/ast/vector.h"
#include "src/ast/workgroup_decoration.h"
#include "src/sem/array.h"
#include "src/sem/atomic_type.h"
#include "src/sem/call.h"
#include "src/sem/depth_texture_type.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/pointer_type.h"
#include "src/sem/reference_type.h"
#include "src/sem/sampled_texture_type.h"
#include "src/sem/sampler_type.h"
#include "src/sem/statement.h"
#include "src/sem/storage_texture_type.h"
#include "src/sem/struct.h"
#include "src/sem/variable.h"
#include "src/utils/get_or_create.h"
#include "src/utils/math.h"
#include "src/utils/scoped_assignment.h"

namespace tint {
namespace resolver {
namespace {

using IntrinsicType = tint::sem::IntrinsicType;

bool IsValidStorageTextureDimension(ast::TextureDimension dim) {
  switch (dim) {
    case ast::TextureDimension::k1d:
    case ast::TextureDimension::k2d:
    case ast::TextureDimension::k2dArray:
    case ast::TextureDimension::k3d:
      return true;
    default:
      return false;
  }
}

bool IsValidStorageTextureImageFormat(ast::ImageFormat format) {
  switch (format) {
    case ast::ImageFormat::kR32Uint:
    case ast::ImageFormat::kR32Sint:
    case ast::ImageFormat::kR32Float:
    case ast::ImageFormat::kRg32Uint:
    case ast::ImageFormat::kRg32Sint:
    case ast::ImageFormat::kRg32Float:
    case ast::ImageFormat::kRgba8Unorm:
    case ast::ImageFormat::kRgba8Snorm:
    case ast::ImageFormat::kRgba8Uint:
    case ast::ImageFormat::kRgba8Sint:
    case ast::ImageFormat::kRgba16Uint:
    case ast::ImageFormat::kRgba16Sint:
    case ast::ImageFormat::kRgba16Float:
    case ast::ImageFormat::kRgba32Uint:
    case ast::ImageFormat::kRgba32Sint:
    case ast::ImageFormat::kRgba32Float:
      return true;
    default:
      return false;
  }
}

/// @returns true if the decoration list contains a
/// ast::DisableValidationDecoration with the validation mode equal to
/// `validation`
bool IsValidationDisabled(const ast::DecorationList& decorations,
                          ast::DisabledValidation validation) {
  for (auto* decoration : decorations) {
    if (auto* dv = decoration->As<ast::DisableValidationDecoration>()) {
      if (dv->Validation() == validation) {
        return true;
      }
    }
  }
  return false;
}

// Helper to stringify a pipeline IO decoration.
std::string deco_to_str(const ast::Decoration* deco) {
  std::stringstream str;
  if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
    str << "builtin(" << builtin->value() << ")";
  } else if (auto* location = deco->As<ast::LocationDecoration>()) {
    str << "location(" << location->value() << ")";
  }
  return str.str();
}
}  // namespace

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

Resolver::~Resolver() = default;

void Resolver::set_referenced_from_function_if_needed(VariableInfo* var,
                                                      bool local) {
  if (current_function_ == nullptr) {
    return;
  }

  if (var->kind != VariableKind::kGlobal) {
    return;
  }

  current_function_->referenced_module_vars.add(var);
  if (local) {
    current_function_->local_referenced_module_vars.add(var);
  }
}

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

  bool result = ResolveInternal();

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

  // Even if resolving failed, create all the semantic nodes for information we
  // did generate.
  CreateSemanticNodes();

  return result;
}

// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
bool Resolver::IsPlain(const sem::Type* type) const {
  return type->is_scalar() || type->Is<sem::Atomic>() ||
         type->Is<sem::Vector>() || type->Is<sem::Matrix>() ||
         type->Is<sem::Array>() || type->Is<sem::Struct>();
}

// https://gpuweb.github.io/gpuweb/wgsl/#atomic-free
bool Resolver::IsAtomicFreePlain(const sem::Type* type) const {
  if (type->Is<sem::Atomic>()) {
    return false;
  }

  if (type->is_scalar() || type->Is<sem::Vector>() || type->Is<sem::Matrix>()) {
    return true;
  }

  if (auto* arr = type->As<sem::Array>()) {
    return IsAtomicFreePlain(arr->ElemType());
  }

  if (auto* str = type->As<sem::Struct>()) {
    for (auto* m : str->Members()) {
      if (!IsAtomicFreePlain(m->Type())) {
        return false;
      }
    }
    return true;
  }

  return false;
}

// https://gpuweb.github.io/gpuweb/wgsl.html#storable-types
bool Resolver::IsStorable(const sem::Type* type) const {
  return IsPlain(type) || type->Is<sem::Texture>() || type->Is<sem::Sampler>();
}

// https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable-types
bool Resolver::IsHostShareable(const sem::Type* type) const {
  if (type->IsAnyOf<sem::I32, sem::U32, sem::F32>()) {
    return true;
  }
  if (auto* vec = type->As<sem::Vector>()) {
    return IsHostShareable(vec->type());
  }
  if (auto* mat = type->As<sem::Matrix>()) {
    return IsHostShareable(mat->type());
  }
  if (auto* arr = type->As<sem::Array>()) {
    return IsHostShareable(arr->ElemType());
  }
  if (auto* str = type->As<sem::Struct>()) {
    for (auto* member : str->Members()) {
      if (!IsHostShareable(member->Type())) {
        return false;
      }
    }
    return true;
  }
  if (auto* atomic = type->As<sem::Atomic>()) {
    return IsHostShareable(atomic->Type());
  }
  return false;
}

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

  // Process everything else in the order they appear in the module. This is
  // necessary for validation of use-before-declaration.
  for (auto* decl : builder_->AST().GlobalDeclarations()) {
    if (auto* td = decl->As<ast::TypeDecl>()) {
      Mark(td);
      if (!TypeDecl(td)) {
        return false;
      }
    } else if (auto* func = decl->As<ast::Function>()) {
      Mark(func);
      if (!Function(func)) {
        return false;
      }
    } else if (auto* var = decl->As<ast::Variable>()) {
      Mark(var);
      if (!GlobalVariable(var)) {
        return false;
      }
    } else {
      TINT_UNREACHABLE(Resolver, diagnostics_)
          << "unhandled global declaration: " << decl->TypeInfo().name;
      return false;
    }
  }

  if (!ValidatePipelineStages()) {
    return false;
  }
  if (!ValidateAtomicUses()) {
    return false;
  }

  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"
          << "Content: " << builder_->str(node) << "\n"
          << "Pointer: " << node;
      result = false;
    }
  }

  return result;
}

sem::Type* Resolver::Type(const ast::Type* ty) {
  Mark(ty);
  auto* s = [&]() -> sem::Type* {
    if (ty->Is<ast::Void>()) {
      return builder_->create<sem::Void>();
    }
    if (ty->Is<ast::Bool>()) {
      return builder_->create<sem::Bool>();
    }
    if (ty->Is<ast::I32>()) {
      return builder_->create<sem::I32>();
    }
    if (ty->Is<ast::U32>()) {
      return builder_->create<sem::U32>();
    }
    if (ty->Is<ast::F32>()) {
      return builder_->create<sem::F32>();
    }
    if (auto* t = ty->As<ast::Vector>()) {
      if (auto* el = Type(t->type())) {
        return builder_->create<sem::Vector>(const_cast<sem::Type*>(el),
                                             t->size());
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::Matrix>()) {
      if (auto* el = Type(t->type())) {
        if (auto* column_type = builder_->create<sem::Vector>(
                const_cast<sem::Type*>(el), t->rows())) {
          if (auto* matrix_type =
                  builder_->create<sem::Matrix>(column_type, t->columns())) {
            if (ValidateMatrix(matrix_type, t->source())) {
              return matrix_type;
            }
          }
        }
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::Array>()) {
      return Array(t);
    }
    if (auto* t = ty->As<ast::Atomic>()) {
      if (auto* el = Type(t->type())) {
        auto* a = builder_->create<sem::Atomic>(const_cast<sem::Type*>(el));
        if (!ValidateAtomic(t, a)) {
          return nullptr;
        }
        return a;
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::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>(const_cast<sem::Type*>(el),
                                              t->storage_class(), access);
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::Sampler>()) {
      return builder_->create<sem::Sampler>(t->kind());
    }
    if (auto* t = ty->As<ast::SampledTexture>()) {
      if (auto* el = Type(t->type())) {
        return builder_->create<sem::SampledTexture>(
            t->dim(), const_cast<sem::Type*>(el));
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::MultisampledTexture>()) {
      if (auto* el = Type(t->type())) {
        return builder_->create<sem::MultisampledTexture>(
            t->dim(), const_cast<sem::Type*>(el));
      }
      return nullptr;
    }
    if (auto* t = ty->As<ast::DepthTexture>()) {
      return builder_->create<sem::DepthTexture>(t->dim());
    }
    if (auto* t = ty->As<ast::StorageTexture>()) {
      if (auto* el = Type(t->type())) {
        if (!ValidateStorageTexture(t)) {
          return nullptr;
        }
        return builder_->create<sem::StorageTexture>(
            t->dim(), t->image_format(), t->access(),
            const_cast<sem::Type*>(el));
      }
      return nullptr;
    }
    if (ty->As<ast::ExternalTexture>()) {
      return builder_->create<sem::ExternalTexture>();
    }
    if (auto* t = ty->As<ast::TypeName>()) {
      auto it = named_type_info_.find(t->name());
      if (it == named_type_info_.end()) {
        AddError(
            "unknown type '" + builder_->Symbols().NameFor(t->name()) + "'",
            t->source());
        return nullptr;
      }
      return it->second.sem;
    }
    TINT_UNREACHABLE(Resolver, diagnostics_)
        << "Unhandled ast::Type: " << ty->TypeInfo().name;
    return nullptr;
  }();

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

bool Resolver::ValidateAtomic(const ast::Atomic* a, const sem::Atomic* s) {
  // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
  // T must be either u32 or i32.
  if (!s->Type()->IsAnyOf<sem::U32, sem::I32>()) {
    AddError("atomic only supports i32 or u32 types", a->type()->source());
    return false;
  }
  return true;
}

bool Resolver::ValidateAtomicUses() {
  // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
  // Atomic types may only be instantiated by variables in the workgroup storage
  // class or by storage buffer variables with a read_write access mode.
  for (auto sm : atomic_members_) {
    auto* structure = sm.structure;
    for (auto usage : structure->StorageClassUsage()) {
      if (usage == ast::StorageClass::kWorkgroup) {
        continue;
      }
      if (usage != ast::StorageClass::kStorage) {
        // TODO(crbug.com/tint/901): Validate that the access mode is
        // read_write.
        auto* member = structure->Members()[sm.index];
        AddError(
            "atomic types can only be used in storage classes workgroup or "
            "storage, but was used by storage class " +
                std::string(ast::str(usage)),
            member->Declaration()->type()->source());
        // TODO(crbug.com/tint/901): Add note pointing at where the usage came
        // from.
        return false;
      }
    }
  }
  return true;
}

bool Resolver::ValidateStorageTexture(const ast::StorageTexture* t) {
  switch (t->access()) {
    case ast::Access::kUndefined:
      AddError("storage textures must have access control", t->source());
      return false;
    case ast::Access::kReadWrite:
      AddError("storage textures only support read-only and write-only access",
               t->source());
      return false;

    case ast::Access::kRead:
    case ast::Access::kWrite:
      break;
  }

  if (!IsValidStorageTextureDimension(t->dim())) {
    AddError("cube dimensions for storage textures are not supported",
             t->source());
    return false;
  }

  if (!IsValidStorageTextureImageFormat(t->image_format())) {
    AddError(
        "image format must be one of the texel formats specified for storage "
        "textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
        t->source());
    return false;
  }
  return true;
}

Resolver::VariableInfo* Resolver::Variable(ast::Variable* var,
                                           VariableKind kind) {
  if (variable_to_info_.count(var)) {
    TINT_ICE(Resolver, diagnostics_)
        << "Variable " << builder_->Symbols().NameFor(var->symbol())
        << " already resolved";
    return nullptr;
  }

  std::string type_name;
  const sem::Type* storage_type = nullptr;

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

  std::string rhs_type_name;
  const sem::Type* rhs_type = nullptr;

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

    // Fetch the constructor's type
    rhs_type_name = TypeNameOf(ctor);
    rhs_type = TypeOf(ctor);
    if (!rhs_type) {
      return nullptr;
    }

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

      type_name = rhs_type_name;
      storage_type = rhs_type->UnwrapRef();  // Implicit load of RHS
    }
  } else if (var->is_const() && kind != VariableKind::kParameter &&
             !ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
    AddError("let declarations must have initializers", var->source());
    return nullptr;
  }

  if (!storage_type) {
    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) {
    if (storage_type->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 decoration. The
      // storage class will always be handle.
      storage_class = ast::StorageClass::kUniformConstant;
    } else if (kind == VariableKind::kLocal && !var->is_const()) {
      storage_class = ast::StorageClass::kFunction;
    }
  }

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

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

  if (rhs_type && !ValidateVariableConstructor(var, storage_type, type_name,
                                               rhs_type, rhs_type_name)) {
    return nullptr;
  }

  auto* info = variable_infos_.Create(var, const_cast<sem::Type*>(type),
                                      type_name, storage_class, access, kind);
  variable_to_info_.emplace(var, info);

  return info;
}

ast::AccessControl 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::kUniformConstant:
      return ast::Access::kRead;
    default:
      break;
  }
  return ast::Access::kReadWrite;
}

bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
                                           const sem::Type* storage_type,
                                           const std::string& type_name,
                                           const sem::Type* rhs_type,
                                           const std::string& rhs_type_name) {
  auto* value_type = rhs_type->UnwrapRef();  // Implicit load of RHS

  // Value type has to match storage type
  if (storage_type != value_type) {
    std::string decl = var->is_const() ? "let" : "var";
    AddError("cannot initialize " + decl + " of type '" + type_name +
                 "' with value of type '" + rhs_type_name + "'",
             var->source());
    return false;
  }
  return true;
}

bool Resolver::GlobalVariable(ast::Variable* var) {
  if (variable_stack_.has(var->symbol())) {
    AddError("v-0011",
             "redeclared global identifier '" +
                 builder_->Symbols().NameFor(var->symbol()) + "'",
             var->source());
    return false;
  }

  auto* info = Variable(var, VariableKind::kGlobal);
  if (!info) {
    return false;
  }
  variable_stack_.set_global(var->symbol(), info);

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

  for (auto* deco : var->decorations()) {
    Mark(deco);

    if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
      // Track the constant IDs that are specified in the shader.
      if (override_deco->HasValue()) {
        constant_ids_.emplace(override_deco->value(), info);
      }
    }
  }

  if (!ValidateNoDuplicateDecorations(var->decorations())) {
    return false;
  }

  if (auto bp = var->binding_point()) {
    info->binding_point = {bp.group->value(), bp.binding->value()};
  }

  if (!ValidateGlobalVariable(info)) {
    return false;
  }

  if (!ApplyStorageClassUsageToType(
          info->storage_class, const_cast<sem::Type*>(info->type->UnwrapRef()),
          var->source())) {
    AddNote("while instantiating variable " +
                builder_->Symbols().NameFor(var->symbol()),
            var->source());
    return false;
  }

  return true;
}

bool Resolver::ValidateGlobalVariable(const VariableInfo* info) {
  auto duplicate_func = symbol_to_function_.find(info->declaration->symbol());
  if (duplicate_func != symbol_to_function_.end()) {
    AddError("v-2000",
             "duplicate declaration '" +
                 builder_->Symbols().NameFor(info->declaration->symbol()) + "'",
             info->declaration->source());
    AddNote("'" + builder_->Symbols().NameFor(info->declaration->symbol()) +
                "' first declared here:",
            duplicate_func->second->declaration->source());
    return false;
  }

  if (!ValidateNoDuplicateDecorations(info->declaration->decorations())) {
    return false;
  }

  for (auto* deco : info->declaration->decorations()) {
    if (info->declaration->is_const()) {
      if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
        if (override_deco->HasValue()) {
          uint32_t id = override_deco->value();
          auto itr = constant_ids_.find(id);
          if (itr != constant_ids_.end() && itr->second != info) {
            AddError("pipeline constant IDs must be unique", deco->source());
            AddNote("a pipeline constant with an ID of " + std::to_string(id) +
                        " was previously declared "
                        "here:",
                    ast::GetDecoration<ast::OverrideDecoration>(
                        itr->second->declaration->decorations())
                        ->source());
            return false;
          }
          if (id > 65535) {
            AddError("pipeline constant IDs must be between 0 and 65535",
                     deco->source());
            return false;
          }
        }
      } else {
        AddError("decoration is not valid for constants", deco->source());
        return false;
      }
    } else {
      bool is_shader_io_decoration =
          deco->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
                        ast::LocationDecoration>();
      bool has_io_storage_class =
          info->storage_class == ast::StorageClass::kInput ||
          info->storage_class == ast::StorageClass::kOutput;
      if (!(deco->IsAnyOf<ast::BindingDecoration, ast::GroupDecoration,
                          ast::InternalDecoration>()) &&
          (!is_shader_io_decoration || !has_io_storage_class)) {
        AddError("decoration is not valid for variables", deco->source());
        return false;
      }
    }
  }

  auto binding_point = info->declaration->binding_point();
  switch (info->storage_class) {
    case ast::StorageClass::kUniform:
    case ast::StorageClass::kStorage:
    case ast::StorageClass::kUniformConstant: {
      // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
      // Each resource variable must be declared with both group and binding
      // attributes.
      if (!binding_point) {
        AddError(
            "resource variables require [[group]] and [[binding]] "
            "decorations",
            info->declaration->source());
        return false;
      }
      break;
    }
    default:
      if (binding_point.binding || binding_point.group) {
        // https://gpuweb.github.io/gpuweb/wgsl/#attribute-binding
        // Must only be applied to a resource variable
        AddError(
            "non-resource variables must not have [[group]] or [[binding]] "
            "decorations",
            info->declaration->source());
        return false;
      }
  }

  // https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration
  // The access mode always has a default, and except for variables in the
  // storage storage class, must not be written.
  if (info->storage_class != ast::StorageClass::kStorage &&
      info->declaration->declared_access() != ast::Access::kUndefined) {
    AddError(
        "variables declared not declared in the <storage> storage class must "
        "not declare an access control",
        info->declaration->source());
    return false;
  }

  switch (info->storage_class) {
    case ast::StorageClass::kStorage: {
      // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
      // A variable in the storage storage class is a storage buffer variable.
      // Its store type must be a host-shareable structure type with block
      // attribute, satisfying the storage class constraints.

      auto* str = info->type->UnwrapRef()->As<sem::Struct>();

      if (!str) {
        AddError(
            "variables declared in the <storage> storage class must be of a "
            "structure type",
            info->declaration->source());
        return false;
      }

      if (!str->IsBlockDecorated()) {
        AddError(
            "structure used as a storage buffer must be declared with the "
            "[[block]] decoration",
            str->Declaration()->source());
        if (info->declaration->source().range.begin.line) {
          AddNote("structure used as storage buffer here",
                  info->declaration->source());
        }
        return false;
      }
      break;
    }
    case ast::StorageClass::kUniform: {
      // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
      // A variable in the uniform storage class is a uniform buffer variable.
      // Its store type must be a host-shareable structure type with block
      // attribute, satisfying the storage class constraints.
      auto* str = info->type->UnwrapRef()->As<sem::Struct>();
      if (!str) {
        AddError(
            "variables declared in the <uniform> storage class must be of a "
            "structure type",
            info->declaration->source());
        return false;
      }

      if (!str->IsBlockDecorated()) {
        AddError(
            "structure used as a uniform buffer must be declared with the "
            "[[block]] decoration",
            str->Declaration()->source());
        if (info->declaration->source().range.begin.line) {
          AddNote("structure used as uniform buffer here",
                  info->declaration->source());
        }
        return false;
      }

      for (auto* member : str->Members()) {
        if (auto* arr = member->Type()->As<sem::Array>()) {
          if (arr->IsRuntimeSized()) {
            AddError(
                "structure containing a runtime sized array "
                "cannot be used as a uniform buffer",
                info->declaration->source());
            AddNote("structure is declared here", str->Declaration()->source());
            return false;
          }
        }
      }

      break;
    }
    default:
      break;
  }

  return ValidateVariable(info);
}

bool Resolver::ValidateVariable(const VariableInfo* info) {
  auto* var = info->declaration;
  auto* storage_type = info->type->UnwrapRef();

  if (!var->is_const() && !IsStorable(storage_type)) {
    AddError(storage_type->FriendlyName(builder_->Symbols()) +
                 " cannot be used as the type of a var",
             var->source());
    return false;
  }

  if (auto* r = storage_type->As<sem::Array>()) {
    if (r->IsRuntimeSized()) {
      AddError("v-0015",
               "runtime arrays may only appear as the last member of a struct",
               var->source());
      return false;
    }
  }

  if (auto* r = storage_type->As<sem::MultisampledTexture>()) {
    if (r->dim() != ast::TextureDimension::k2d) {
      AddError("only 2d multisampled textures are supported", var->source());
      return false;
    }

    if (!r->type()->UnwrapRef()->is_numeric_scalar()) {
      AddError("texture_multisampled_2d<type>: type must be f32, i32 or u32",
               var->source());
      return false;
    }
  }

  if (storage_type->is_handle() &&
      var->declared_storage_class() != ast::StorageClass::kNone) {
    // 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 decoration. The
    // storage class will always be handle.
    AddError("variables of type '" + info->type_name +
                 "' must not have a storage class",
             var->source());
    return false;
  }

  if (!IsValidationDisabled(var->decorations(),
                            ast::DisabledValidation::kIgnoreStorageClass) &&
      (var->declared_storage_class() == ast::StorageClass::kInput ||
       var->declared_storage_class() == ast::StorageClass::kOutput)) {
    AddError("invalid use of input/output storage class", var->source());
    return false;
  }

  // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
  // Atomic types may only be instantiated by variables in the workgroup storage
  // class or by storage buffer variables with a read_write access mode.
  if (info->type->UnwrapRef()->Is<sem::Atomic>() &&
      info->storage_class != ast::StorageClass::kWorkgroup) {
    // Storage buffers require a structure, so just check for workgroup
    // storage here.
    AddError("atomic var requires workgroup storage",
             info->declaration->type()->source());
    return false;
  }

  return true;
}

bool Resolver::ValidateParameter(const ast::Function* func,
                                 const VariableInfo* info) {
  if (!ValidateVariable(info)) {
    return false;
  }

  for (auto* deco : info->declaration->decorations()) {
    if (!func->IsEntryPoint() &&
        !IsValidationDisabled(
            info->declaration->decorations(),
            ast::DisabledValidation::kIgnoreAtomicFunctionParameter)) {
      AddError("decoration is not valid for function parameters",
               deco->source());
      return false;
    }

    if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
      if (!ValidateBuiltinDecoration(builtin, info->type)) {
        return false;
      }
    } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
      if (!ValidateInterpolateDecoration(interpolate, info->type)) {
        return false;
      }
    } else if (!deco->IsAnyOf<ast::LocationDecoration,
                              ast::InternalDecoration>() &&
               !(IsValidationDisabled(
                     info->declaration->decorations(),
                     ast::DisabledValidation::kEntryPointParameter) ||
                 IsValidationDisabled(info->declaration->decorations(),
                                      ast::DisabledValidation::
                                          kIgnoreAtomicFunctionParameter))) {
      AddError("decoration is not valid for function parameters",
               deco->source());
      return false;
    }
  }
  return true;
}

bool Resolver::ValidateBuiltinDecoration(const ast::BuiltinDecoration* deco,
                                         const sem::Type* storage_type) {
  auto* type = storage_type->UnwrapRef();
  switch (deco->value()) {
    case ast::Builtin::kPosition:
      if (!(type->is_float_vector() && type->As<sem::Vector>()->size() == 4)) {
        AddError("store type of " + deco_to_str(deco) + " must be 'vec4<f32>'",
                 deco->source());
        return false;
      }
      break;
    case ast::Builtin::kGlobalInvocationId:
    case ast::Builtin::kLocalInvocationId:
    case ast::Builtin::kWorkgroupId:
      if (!(type->is_unsigned_integer_vector() &&
            type->As<sem::Vector>()->size() == 3)) {
        AddError("store type of " + deco_to_str(deco) + " must be 'vec3<u32>'",
                 deco->source());
        return false;
      }
      break;
    case ast::Builtin::kFragDepth:
      if (!type->Is<sem::F32>()) {
        AddError("store type of " + deco_to_str(deco) + " must be 'f32'",
                 deco->source());
        return false;
      }
      break;
    case ast::Builtin::kFrontFacing:
      if (!type->Is<sem::Bool>()) {
        AddError("store type of " + deco_to_str(deco) + " must be 'bool'",
                 deco->source());
        return false;
      }
      break;
    case ast::Builtin::kLocalInvocationIndex:
    case ast::Builtin::kVertexIndex:
    case ast::Builtin::kInstanceIndex:
    case ast::Builtin::kSampleMask:
    case ast::Builtin::kSampleIndex:
      if (!type->Is<sem::U32>()) {
        AddError("store type of " + deco_to_str(deco) + " must be 'u32'",
                 deco->source());
        return false;
      }
      break;
    default:
      break;
  }
  return true;
}

bool Resolver::ValidateInterpolateDecoration(
    const ast::InterpolateDecoration* deco,
    const sem::Type* storage_type) {
  auto* type = storage_type->UnwrapRef();

  if (!type->is_float_scalar_or_vector()) {
    AddError(
        "store type of interpolate attribute must be floating point scalar or "
        "vector",
        deco->source());
    return false;
  }

  if (deco->type() == ast::InterpolationType::kFlat &&
      deco->sampling() != ast::InterpolationSampling::kNone) {
    AddError("flat interpolation attribute must not have a sampling parameter",
             deco->source());
    return false;
  }

  return true;
}

bool Resolver::ValidateFunction(const ast::Function* func,
                                const FunctionInfo* info) {
  auto func_it = symbol_to_function_.find(func->symbol());
  if (func_it != symbol_to_function_.end()) {
    AddError("v-0016",
             "duplicate function named '" +
                 builder_->Symbols().NameFor(func->symbol()) + "'",
             func->source());
    AddNote("first function declared here",
            func_it->second->declaration->source());
    return false;
  }

  bool is_global = false;
  VariableInfo* var;
  if (variable_stack_.get(func->symbol(), &var, &is_global)) {
    if (is_global) {
      AddError("v-2000",
               "duplicate declaration '" +
                   builder_->Symbols().NameFor(func->symbol()) + "'",
               func->source());
      AddNote("'" + builder_->Symbols().NameFor(func->symbol()) +
                  "' first declared here:",
              var->declaration->source());
      return false;
    }
  }

  auto stage_deco_count = 0;
  auto workgroup_deco_count = 0;
  for (auto* deco : func->decorations()) {
    if (deco->Is<ast::StageDecoration>()) {
      stage_deco_count++;
    } else if (deco->Is<ast::WorkgroupDecoration>()) {
      workgroup_deco_count++;
      if (func->pipeline_stage() != ast::PipelineStage::kCompute) {
        AddError(
            "the workgroup_size attribute is only valid for compute stages",
            deco->source());
        return false;
      }
    } else if (!deco->Is<ast::InternalDecoration>()) {
      AddError("decoration is not valid for functions", deco->source());
      return false;
    }
  }

  for (auto* param : func->params()) {
    if (!ValidateParameter(func, variable_to_info_.at(param))) {
      return false;
    }
  }

  if (!info->return_type->Is<sem::Void>()) {
    if (!IsAtomicFreePlain(info->return_type)) {
      AddError("function return type must be an atomic-free plain type",
               func->return_type()->source());
      return false;
    }

    if (func->body()) {
      if (!func->get_last_statement() ||
          !func->get_last_statement()->Is<ast::ReturnStatement>()) {
        AddError("v-0002", "non-void function must end with a return statement",
                 func->source());
        return false;
      }
    } else if (!IsValidationDisabled(
                   func->decorations(),
                   ast::DisabledValidation::kFunctionHasNoBody)) {
      TINT_ICE(Resolver, diagnostics_)
          << "Function " << builder_->Symbols().NameFor(func->symbol())
          << " has no body";
    }

    for (auto* deco : func->return_type_decorations()) {
      if (!func->IsEntryPoint()) {
        AddError("decoration is not valid for function return types",
                 deco->source());
        return false;
      }

      if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
        if (!ValidateBuiltinDecoration(builtin, info->return_type)) {
          return false;
        }
      } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
        if (!ValidateInterpolateDecoration(interpolate, info->return_type)) {
          return false;
        }
      } else if (!deco->Is<ast::LocationDecoration>()) {
        AddError("decoration is not valid for entry point return types",
                 deco->source());
        return false;
      }
    }
  }

  if (func->IsEntryPoint()) {
    if (!ValidateEntryPoint(func, info)) {
      return false;
    }
  }

  return true;
}

bool Resolver::ValidateEntryPoint(const ast::Function* func,
                                  const FunctionInfo* info) {
  // Use a lambda to validate the entry point decorations for a type.
  // Persistent state is used to track which builtins and locations have
  // already been seen, in order to catch conflicts.
  // TODO(jrprice): This state could be stored in FunctionInfo instead, and
  // then passed to sem::Function since it would be useful there too.
  std::unordered_set<ast::Builtin> builtins;
  std::unordered_set<uint32_t> locations;
  enum class ParamOrRetType {
    kParameter,
    kReturnType,
  };

  // Inner lambda that is applied to a type and all of its members.
  auto validate_entry_point_decorations_inner =
      [&](const ast::DecorationList& decos, sem::Type* ty, Source source,
          ParamOrRetType param_or_ret, bool is_struct_member) {
        // Scan decorations for pipeline IO attributes.
        // Check for overlap with attributes that have been seen previously.
        ast::Decoration* pipeline_io_attribute = nullptr;
        for (auto* deco : decos) {
          if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
            if (pipeline_io_attribute) {
              AddError("multiple entry point IO attributes", deco->source());
              AddNote(
                  "previously consumed " + deco_to_str(pipeline_io_attribute),
                  pipeline_io_attribute->source());
              return false;
            }
            pipeline_io_attribute = deco;

            if (builtins.count(builtin->value())) {
              AddError(
                  deco_to_str(builtin) +
                      " attribute appears multiple times as pipeline " +
                      (param_or_ret == ParamOrRetType::kParameter ? "input"
                                                                  : "output"),
                  func->source());
              return false;
            }
            builtins.emplace(builtin->value());

          } else if (auto* location = deco->As<ast::LocationDecoration>()) {
            if (pipeline_io_attribute) {
              AddError("multiple entry point IO attributes", deco->source());
              AddNote(
                  "previously consumed " + deco_to_str(pipeline_io_attribute),
                  pipeline_io_attribute->source());
              return false;
            }
            pipeline_io_attribute = deco;

            if (locations.count(location->value())) {
              AddError(
                  deco_to_str(location) +
                      " attribute appears multiple times as pipeline " +
                      (param_or_ret == ParamOrRetType::kParameter ? "input"
                                                                  : "output"),
                  func->source());
              return false;
            }
            locations.emplace(location->value());
          }
        }

        // Check that we saw a pipeline IO attribute iff we need one.
        if (ty->Is<sem::Struct>()) {
          if (pipeline_io_attribute) {
            AddError(
                "entry point IO attributes must not be used on structure " +
                    std::string(param_or_ret == ParamOrRetType::kParameter
                                    ? "parameters"
                                    : "return types"),
                pipeline_io_attribute->source());
            return false;
          }
        } else if (!IsValidationDisabled(
                       decos, ast::DisabledValidation::kEntryPointParameter)) {
          if (!pipeline_io_attribute) {
            std::string err = "missing entry point IO attribute";
            if (!is_struct_member) {
              err += (param_or_ret == ParamOrRetType::kParameter
                          ? " on parameter"
                          : " on return type");
            }
            AddError(err, source);
            return false;
          }

          // Check that all user defined attributes are numeric scalars, vectors
          // of numeric scalars.
          // Testing for being a struct is handled by the if portion above.
          if (!pipeline_io_attribute->Is<ast::BuiltinDecoration>()) {
            if (!ty->is_numeric_scalar_or_vector()) {
              AddError(
                  "User defined entry point IO types must be a numeric scalar, "
                  "a numeric vector, or a structure",
                  source);
              return false;
            }
          }
        }

        return true;
      };

  // Outer lambda for validating the entry point decorations for a type.
  auto validate_entry_point_decorations = [&](const ast::DecorationList& decos,
                                              sem::Type* ty, Source source,
                                              ParamOrRetType param_or_ret) {
    // Validate the decorations for the type.
    if (!validate_entry_point_decorations_inner(decos, ty, source, param_or_ret,
                                                false)) {
      return false;
    }

    if (auto* str = ty->As<sem::Struct>()) {
      // Validate the decorations for each struct members, and also check for
      // invalid member types.
      for (auto* member : str->Members()) {
        if (member->Type()->Is<sem::Struct>()) {
          AddError("entry point IO types cannot contain nested structures",
                   member->Declaration()->source());
          AddNote("while analysing entry point " +
                      builder_->Symbols().NameFor(func->symbol()),
                  func->source());
          return false;
        }

        if (auto* arr = member->Type()->As<sem::Array>()) {
          if (arr->IsRuntimeSized()) {
            AddError("entry point IO types cannot contain runtime sized arrays",
                     member->Declaration()->source());
            AddNote("while analysing entry point " +
                        builder_->Symbols().NameFor(func->symbol()),
                    func->source());
            return false;
          }
        }

        if (!validate_entry_point_decorations_inner(
                member->Declaration()->decorations(), member->Type(),
                member->Declaration()->source(), param_or_ret, true)) {
          AddNote("while analysing entry point " +
                      builder_->Symbols().NameFor(func->symbol()),
                  func->source());
          return false;
        }
      }
    }

    return true;
  };

  for (auto* param : info->parameters) {
    if (!validate_entry_point_decorations(
            param->declaration->decorations(), param->type,
            param->declaration->source(), ParamOrRetType::kParameter)) {
      return false;
    }
  }

  // Clear IO sets after parameter validation. Builtin and location attributes
  // in return types should be validated independently from those used in
  // parameters.
  builtins.clear();
  locations.clear();

  if (!info->return_type->Is<sem::Void>()) {
    if (!validate_entry_point_decorations(func->return_type_decorations(),
                                          info->return_type, func->source(),
                                          ParamOrRetType::kReturnType)) {
      return false;
    }
  }

  if (func->pipeline_stage() == ast::PipelineStage::kVertex &&
      builtins.count(ast::Builtin::kPosition) == 0) {
    // Check module-scope variables, as the SPIR-V sanitizer generates these.
    bool found = false;
    for (auto* var : info->referenced_module_vars) {
      if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
              var->declaration->decorations())) {
        if (builtin->value() == ast::Builtin::kPosition) {
          found = true;
          break;
        }
      }
    }
    if (!found) {
      AddError(
          "a vertex shader must include the 'position' builtin in its return "
          "type",
          func->source());
      return false;
    }
  }

  // Validate there are no resource variable binding collisions
  std::unordered_map<sem::BindingPoint, const ast::Variable*> binding_points;
  for (auto* var_info : info->referenced_module_vars) {
    if (!var_info->declaration->binding_point()) {
      continue;
    }
    auto bp = var_info->binding_point;
    auto res = binding_points.emplace(bp, var_info->declaration);
    if (!res.second &&
        !IsValidationDisabled(
            var_info->declaration->decorations(),
            ast::DisabledValidation::kBindingPointCollision) &&
        !IsValidationDisabled(
            res.first->second->decorations(),
            ast::DisabledValidation::kBindingPointCollision)) {
      // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
      // Bindings must not alias within a shader stage: two different
      // variables in the resource interface of a given shader must not have
      // the same group and binding values, when considered as a pair of
      // values.
      auto func_name = builder_->Symbols().NameFor(info->declaration->symbol());
      AddError("entry point '" + func_name +
                   "' references multiple variables that use the "
                   "same resource binding [[group(" +
                   std::to_string(bp.group) + "), binding(" +
                   std::to_string(bp.binding) + ")]]",
               var_info->declaration->source());
      AddNote("first resource binding usage declared here",
              res.first->second->source());
      return false;
    }
  }

  return true;
}

bool Resolver::Function(ast::Function* func) {
  auto* info = function_infos_.Create<FunctionInfo>(func);

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

  TINT_SCOPED_ASSIGNMENT(current_function_, info);

  variable_stack_.push_scope();
  for (auto* param : func->params()) {
    Mark(param);
    auto* param_info = Variable(param, VariableKind::kParameter);
    if (!param_info) {
      return false;
    }

    // TODO(amaiorano): Validate parameter decorations
    for (auto* deco : param->decorations()) {
      Mark(deco);
    }
    if (!ValidateNoDuplicateDecorations(param->decorations())) {
      return false;
    }

    variable_stack_.set(param->symbol(), param_info);
    info->parameters.emplace_back(param_info);

    if (!ApplyStorageClassUsageToType(param->declared_storage_class(),
                                      param_info->type, param->source())) {
      AddNote("while instantiating parameter " +
                  builder_->Symbols().NameFor(param->symbol()),
              param->source());
      return false;
    }

    if (auto* str = param_info->type->As<sem::Struct>()) {
      switch (func->pipeline_stage()) {
        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;
      }
    }
  }

  if (auto* ty = func->return_type()) {
    info->return_type = Type(ty);
    info->return_type_name = ty->FriendlyName(builder_->Symbols());
    if (!info->return_type) {
      return false;
    }
  } else {
    info->return_type = builder_->create<sem::Void>();
    info->return_type_name =
        info->return_type->FriendlyName(builder_->Symbols());
  }

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

    switch (func->pipeline_stage()) {
      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;
    }
  }

  if (func->body()) {
    Mark(func->body());
    if (current_statement_) {
      TINT_ICE(Resolver, diagnostics_)
          << "Resolver::Function() called with a current statement";
      return false;
    }
    auto* sem_block = builder_->create<sem::FunctionBlockStatement>(func);
    builder_->Sem().Add(func->body(), sem_block);
    TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block);
    if (!BlockScope(func->body(),
                    [&] { return Statements(func->body()->list()); })) {
      return false;
    }
  }
  variable_stack_.pop_scope();

  for (auto* deco : func->decorations()) {
    Mark(deco);
  }
  if (!ValidateNoDuplicateDecorations(func->decorations())) {
    return false;
  }

  for (auto* deco : func->return_type_decorations()) {
    Mark(deco);
  }
  if (!ValidateNoDuplicateDecorations(func->return_type_decorations())) {
    return false;
  }

  // Set work-group size defaults.
  for (int i = 0; i < 3; i++) {
    info->workgroup_size[i].value = 1;
    info->workgroup_size[i].overridable_const = nullptr;
  }

  if (auto* workgroup =
          ast::GetDecoration<ast::WorkgroupDecoration>(func->decorations())) {
    auto values = workgroup->values();
    for (int i = 0; i < 3; i++) {
      // Each argument to this decoration can either be a literal, an
      // identifier for a module-scope constants, or nullptr if not specified.

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

      Mark(values[i]);

      int32_t value = 0;
      if (auto* ident = values[i]->As<ast::IdentifierExpression>()) {
        // We have an identifier of a module-scope constant.
        if (!Identifier(ident)) {
          return false;
        }

        VariableInfo* var;
        if (!variable_stack_.get(ident->symbol(), &var) ||
            !(var->declaration->is_const() && var->type->Is<sem::I32>())) {
          AddError(
              "workgroup_size parameter must be a literal i32 or an i32 "
              "module-scope constant",
              values[i]->source());
          return false;
        }

        // Capture the constant if an [[override]] attribute is present.
        if (ast::HasDecoration<ast::OverrideDecoration>(
                var->declaration->decorations())) {
          info->workgroup_size[i].overridable_const = var->declaration;
        }

        auto* constructor = var->declaration->constructor();
        if (constructor) {
          // Resolve the constructor expression to use as the default value.
          if (!GetScalarConstExprValue(constructor, &value)) {
            return false;
          }
        } else {
          // No constructor means this value must be overriden by the user.
          info->workgroup_size[i].value = 0;
          continue;
        }
      } else if (auto* scalar =
                     values[i]->As<ast::ScalarConstructorExpression>()) {
        // We have a literal.
        Mark(scalar->literal());

        if (!scalar->literal()->Is<ast::IntLiteral>()) {
          AddError(
              "workgroup_size parameter must be a literal i32 or an i32 "
              "module-scope constant",
              values[i]->source());
          return false;
        }

        if (!GetScalarConstExprValue(scalar, &value)) {
          return false;
        }
      }

      // Validate and set the default value for this dimension.
      if (value < 1) {
        AddError("workgroup_size parameter must be a positive i32 value",
                 values[i]->source());
        return false;
      }
      info->workgroup_size[i].value = value;
    }
  }

  if (!ValidateFunction(func, info)) {
    return false;
  }

  // Register the function information _after_ processing the statements. This
  // allows us to catch a function calling itself when determining the call
  // information as this function doesn't exist until it's finished.
  symbol_to_function_[func->symbol()] = info;
  function_to_info_.emplace(func, info);

  return true;
}

bool Resolver::Statements(const ast::StatementList& stmts) {
  for (auto* stmt : stmts) {
    Mark(stmt);
    if (!Statement(stmt)) {
      return false;
    }
  }
  if (!ValidateStatements(stmts)) {
    return false;
  }

  return true;
}

bool Resolver::ValidateStatements(const ast::StatementList& stmts) {
  auto next_stmt = stmts.begin();
  for (auto* stmt : stmts) {
    next_stmt++;
    if (stmt->IsAnyOf<ast::ReturnStatement, ast::BreakStatement,
                      ast::ContinueStatement>()) {
      if (stmt != stmts.back()) {
        AddError("code is unreachable", (*next_stmt)->source());
        return false;
      }
    }
  }
  return true;
}

bool Resolver::Statement(ast::Statement* stmt) {
  sem::Statement* sem_statement;
  if (stmt->As<ast::BlockStatement>()) {
    sem_statement = builder_->create<sem::BlockStatement>(
        stmt->As<ast::BlockStatement>(), current_statement_);
  } else {
    sem_statement = builder_->create<sem::Statement>(stmt, current_statement_);
  }
  builder_->Sem().Add(stmt, sem_statement);

  TINT_SCOPED_ASSIGNMENT(current_statement_, sem_statement);

  if (stmt->Is<ast::ElseStatement>()) {
    TINT_ICE(Resolver, diagnostics_)
        << "Resolver::Statement() encountered an Else statement. Else "
           "statements are embedded in If statements, so should never be "
           "encountered as top-level statements";
    return false;
  }

  if (auto* a = stmt->As<ast::AssignmentStatement>()) {
    return Assignment(a);
  }
  if (auto* b = stmt->As<ast::BlockStatement>()) {
    return BlockScope(b, [&] { return Statements(b->list()); });
  }
  if (stmt->Is<ast::BreakStatement>()) {
    if (!current_block_->FindFirstParent<sem::LoopBlockStatement>() &&
        !current_block_->FindFirstParent<sem::SwitchCaseBlockStatement>()) {
      AddError("break statement must be in a loop or switch case",
               stmt->source());
      return false;
    }
    return true;
  }
  if (auto* c = stmt->As<ast::CallStatement>()) {
    Mark(c->expr());
    if (!Expression(c->expr())) {
      return false;
    }
    if (!ValidateCallStatement(c)) {
      return false;
    }
    return true;
  }
  if (auto* c = stmt->As<ast::CaseStatement>()) {
    return CaseStatement(c);
  }
  if (stmt->Is<ast::ContinueStatement>()) {
    // Set if we've hit the first continue statement in our parent loop
    if (auto* loop_block =
            current_block_->FindFirstParent<sem::LoopBlockStatement>()) {
      if (loop_block->FirstContinue() == size_t(~0)) {
        const_cast<sem::LoopBlockStatement*>(loop_block)
            ->SetFirstContinue(loop_block->Decls().size());
      }
    } else {
      AddError("continue statement must be in a loop", stmt->source());
      return false;
    }

    return true;
  }
  if (stmt->Is<ast::DiscardStatement>()) {
    return true;
  }
  if (stmt->Is<ast::FallthroughStatement>()) {
    return true;
  }
  if (auto* i = stmt->As<ast::IfStatement>()) {
    return IfStatement(i);
  }
  if (auto* l = stmt->As<ast::LoopStatement>()) {
    return LoopStatement(l);
  }
  if (auto* r = stmt->As<ast::ReturnStatement>()) {
    return Return(r);
  }
  if (auto* s = stmt->As<ast::SwitchStatement>()) {
    return Switch(s);
  }
  if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
    return VariableDeclStatement(v);
  }

  AddError(
      "unknown statement type for type determination: " + builder_->str(stmt),
      stmt->source());
  return false;
}

bool Resolver::CaseStatement(ast::CaseStatement* stmt) {
  Mark(stmt->body());
  for (auto* sel : stmt->selectors()) {
    Mark(sel);
  }
  auto* sem_block = builder_->create<sem::SwitchCaseBlockStatement>(
      stmt->body(), current_statement_);
  builder_->Sem().Add(stmt->body(), sem_block);
  TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block);
  return BlockScope(stmt->body(),
                    [&] { return Statements(stmt->body()->list()); });
}

bool Resolver::IfStatement(ast::IfStatement* stmt) {
  Mark(stmt->condition());
  if (!Expression(stmt->condition())) {
    return false;
  }

  auto* cond_type = TypeOf(stmt->condition())->UnwrapRef();
  if (!cond_type->Is<sem::Bool>()) {
    AddError("if statement condition must be bool, got " +
                 cond_type->FriendlyName(builder_->Symbols()),
             stmt->condition()->source());
    return false;
  }

  Mark(stmt->body());
  {
    auto* sem_block =
        builder_->create<sem::BlockStatement>(stmt->body(), current_statement_);
    builder_->Sem().Add(stmt->body(), sem_block);
    TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block);
    if (!BlockScope(stmt->body(),
                    [&] { return Statements(stmt->body()->list()); })) {
      return false;
    }
  }

  for (auto* else_stmt : stmt->else_statements()) {
    Mark(else_stmt);
    auto* sem_else_stmt =
        builder_->create<sem::Statement>(else_stmt, current_statement_);
    builder_->Sem().Add(else_stmt, sem_else_stmt);
    TINT_SCOPED_ASSIGNMENT(current_statement_, sem_else_stmt);
    if (auto* cond = else_stmt->condition()) {
      Mark(cond);
      if (!Expression(cond)) {
        return false;
      }

      auto* else_cond_type = TypeOf(cond)->UnwrapRef();
      if (!else_cond_type->Is<sem::Bool>()) {
        AddError("else statement condition must be bool, got " +
                     else_cond_type->FriendlyName(builder_->Symbols()),
                 cond->source());
        return false;
      }
    }
    Mark(else_stmt->body());
    {
      auto* sem_block = builder_->create<sem::BlockStatement>(
          else_stmt->body(), current_statement_);
      builder_->Sem().Add(else_stmt->body(), sem_block);
      TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block);
      if (!BlockScope(else_stmt->body(),
                      [&] { return Statements(else_stmt->body()->list()); })) {
        return false;
      }
    }
  }
  return true;
}

bool Resolver::LoopStatement(ast::LoopStatement* stmt) {
  // We don't call DetermineBlockStatement on the body and continuing block as
  // these would make their BlockInfo siblings as in the AST, but we want the
  // body BlockInfo to parent the continuing BlockInfo for semantics and
  // validation. Also, we need to set their types differently.
  Mark(stmt->body());

  auto* sem_block_body = builder_->create<sem::LoopBlockStatement>(
      stmt->body(), current_statement_);
  builder_->Sem().Add(stmt->body(), sem_block_body);
  TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block_body);
  return BlockScope(stmt->body(), [&] {
    if (!Statements(stmt->body()->list())) {
      return false;
    }
    if (stmt->continuing()) {  // has_continuing() also checks for empty()
      Mark(stmt->continuing());
    }
    if (stmt->has_continuing()) {
      auto* sem_block_continuing =
          builder_->create<sem::LoopContinuingBlockStatement>(
              stmt->continuing(), current_statement_);
      builder_->Sem().Add(stmt->continuing(), sem_block_continuing);
      TINT_SCOPED_ASSIGNMENT(current_statement_, sem_block_continuing);
      if (!BlockScope(stmt->continuing(),
                      [&] { return Statements(stmt->continuing()->list()); })) {
        return false;
      }
    }
    return true;
  });
}

bool Resolver::Expressions(const ast::ExpressionList& list) {
  for (auto* expr : list) {
    Mark(expr);
    if (!Expression(expr)) {
      return false;
    }
  }
  return true;
}

bool Resolver::Expression(ast::Expression* expr) {
  if (TypeOf(expr)) {
    return true;  // Already resolved
  }

  bool ok = false;
  if (auto* array = expr->As<ast::ArrayAccessorExpression>()) {
    ok = ArrayAccessor(array);
  } else if (auto* bin_op = expr->As<ast::BinaryExpression>()) {
    ok = Binary(bin_op);
  } else if (auto* bitcast = expr->As<ast::BitcastExpression>()) {
    ok = Bitcast(bitcast);
  } else if (auto* call = expr->As<ast::CallExpression>()) {
    ok = Call(call);
  } else if (auto* ctor = expr->As<ast::ConstructorExpression>()) {
    ok = Constructor(ctor);
  } else if (auto* ident = expr->As<ast::IdentifierExpression>()) {
    ok = Identifier(ident);
  } else if (auto* member = expr->As<ast::MemberAccessorExpression>()) {
    ok = MemberAccessor(member);
  } else if (auto* unary = expr->As<ast::UnaryOpExpression>()) {
    ok = UnaryOp(unary);
  } else {
    AddError("unknown expression for type determination", expr->source());
  }

  if (!ok) {
    return false;
  }

  auto* ty = TypeOf(expr);
  if (ty->Is<sem::Atomic>()) {
    AddError("an expression must not evaluate to an atomic type",
             expr->source());
    return false;
  }

  return true;
}

bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) {
  Mark(expr->array());
  if (!Expression(expr->array())) {
    return false;
  }
  auto* idx = expr->idx_expr();
  Mark(idx);
  if (!Expression(idx)) {
    return false;
  }

  auto* res = TypeOf(expr->array());
  auto* parent_type = res->UnwrapRef();
  const sem::Type* ret = nullptr;
  if (auto* arr = parent_type->As<sem::Array>()) {
    ret = arr->ElemType();
  } else if (auto* vec = parent_type->As<sem::Vector>()) {
    ret = vec->type();
  } else if (auto* mat = parent_type->As<sem::Matrix>()) {
    ret = builder_->create<sem::Vector>(mat->type(), mat->rows());
  } else {
    AddError("invalid parent type (" + parent_type->type_name() +
                 ") in array accessor",
             expr->source());
    return false;
  }

  if (!TypeOf(idx)->UnwrapRef()->IsAnyOf<sem::I32, sem::U32>()) {
    AddError("index must be of type 'i32' or 'u32', found: '" +
                 TypeNameOf(idx) + "'",
             idx->source());
    return false;
  }

  if (parent_type->Is<sem::Array>() || parent_type->Is<sem::Matrix>()) {
    if (!res->Is<sem::Reference>()) {
      // TODO(bclayton): expand this to allow any const_expr expression
      // https://github.com/gpuweb/gpuweb/issues/1272
      auto* scalar = idx->As<ast::ScalarConstructorExpression>();
      if (!scalar || !scalar->literal()->As<ast::IntLiteral>()) {
        AddError("index must be signed or unsigned integer literal",
                 idx->source());
        return false;
      }
    }
  }

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

  return true;
}

bool Resolver::Bitcast(ast::BitcastExpression* expr) {
  Mark(expr->expr());
  if (!Expression(expr->expr())) {
    return false;
  }
  auto* ty = Type(expr->type());
  if (!ty) {
    return false;
  }
  if (ty->Is<sem::Pointer>()) {
    AddError("cannot cast to a pointer", expr->source());
    return false;
  }
  SetType(expr, ty, expr->type()->FriendlyName(builder_->Symbols()));
  return true;
}

bool Resolver::Call(ast::CallExpression* call) {
  if (!Expressions(call->params())) {
    return false;
  }

  Mark(call->func());
  auto* ident = call->func();
  auto name = builder_->Symbols().NameFor(ident->symbol());

  auto intrinsic_type = sem::ParseIntrinsicType(name);
  if (intrinsic_type != IntrinsicType::kNone) {
    if (!IntrinsicCall(call, intrinsic_type)) {
      return false;
    }
  } else {
    if (!FunctionCall(call)) {
      return false;
    }
  }

  return true;
}

bool Resolver::ValidateCallStatement(ast::CallStatement* stmt) {
  const sem::Type* return_type = nullptr;
  // A function call is made to either a user declared function or an intrinsic.
  // function_calls_ only maps CallExpression to user declared functions
  auto it = function_calls_.find(stmt->expr());
  if (it != function_calls_.end()) {
    return_type = it->second.function->return_type;
  } else {
    // Must be an intrinsic call
    auto* target = builder_->Sem().Get(stmt->expr())->Target();
    if (auto* intrinsic = target->As<sem::Intrinsic>()) {
      return_type = intrinsic->ReturnType();
    } else {
      TINT_ICE(Resolver, diagnostics_)
          << "call target was not an intrinsic, but a "
          << intrinsic->TypeInfo().name;
    }
  }

  if (!return_type->Is<sem::Void>()) {
    // https://gpuweb.github.io/gpuweb/wgsl/#function-call-statement
    // A function call statement executes a function call where the called
    // function does not return a value. If the called function returns a value,
    // that value must be consumed either through assignment, evaluation in
    // another expression or through use of the ignore built-in function (see
    // § 16.13 Value-steering functions).
    AddError(
        "result of called function was not used. If this was intentional wrap "
        "the function call in ignore()",
        stmt->source());
    return false;
  }
  return true;
}

bool Resolver::IntrinsicCall(ast::CallExpression* call,
                             sem::IntrinsicType intrinsic_type) {
  std::vector<const sem::Type*> arg_tys;
  arg_tys.reserve(call->params().size());
  for (auto* expr : call->params()) {
    arg_tys.emplace_back(TypeOf(expr));
  }

  auto* result =
      intrinsic_table_->Lookup(intrinsic_type, arg_tys, call->source());
  if (!result) {
    return false;
  }

  if (result->IsDeprecated()) {
    AddWarning("use of deprecated intrinsic", call->source());
  }

  builder_->Sem().Add(
      call, builder_->create<sem::Call>(call, result, current_statement_));
  SetType(call, result->ReturnType());

  current_function_->intrinsic_calls.emplace_back(
      IntrinsicCallInfo{call, result});

  return true;
}

bool Resolver::FunctionCall(const ast::CallExpression* call) {
  auto* ident = call->func();
  auto name = builder_->Symbols().NameFor(ident->symbol());

  auto callee_func_it = symbol_to_function_.find(ident->symbol());
  if (callee_func_it == symbol_to_function_.end()) {
    if (current_function_ &&
        current_function_->declaration->symbol() == ident->symbol()) {
      AddError("v-0004",
               "recursion is not permitted. '" + name +
                   "' attempted to call itself.",
               call->source());
    } else {
      AddError("v-0006: unable to find called function: " + name,
               call->source());
    }
    return false;
  }
  auto* callee_func = callee_func_it->second;

  if (current_function_) {
    callee_func->callsites.push_back(call);

    // Note: Requires called functions to be resolved first.
    // This is currently guaranteed as functions must be declared before
    // use.
    current_function_->transitive_calls.add(callee_func);
    for (auto* transitive_call : callee_func->transitive_calls) {
      current_function_->transitive_calls.add(transitive_call);
    }

    // We inherit any referenced variables from the callee.
    for (auto* var : callee_func->referenced_module_vars) {
      set_referenced_from_function_if_needed(var, false);
    }
  }

  // Validate number of arguments match number of parameters
  if (call->params().size() != callee_func->parameters.size()) {
    bool more = call->params().size() > callee_func->parameters.size();
    AddError("too " + (more ? std::string("many") : std::string("few")) +
                 " arguments in call to '" + name + "', expected " +
                 std::to_string(callee_func->parameters.size()) + ", got " +
                 std::to_string(call->params().size()),
             call->source());
    return false;
  }

  // Validate arguments match parameter types
  for (size_t i = 0; i < call->params().size(); ++i) {
    const VariableInfo* param = callee_func->parameters[i];
    const ast::Expression* arg_expr = call->params()[i];
    auto* arg_type = TypeOf(arg_expr)->UnwrapRef();

    if (param->type != arg_type) {
      AddError("type mismatch for argument " + std::to_string(i + 1) +
                   " in call to '" + name + "', expected '" +
                   param->type->FriendlyName(builder_->Symbols()) + "', got '" +
                   arg_type->FriendlyName(builder_->Symbols()) + "'",
               arg_expr->source());
      return false;
    }
  }

  function_calls_.emplace(call,
                          FunctionCallInfo{callee_func, current_statement_});
  SetType(call, callee_func->return_type, callee_func->return_type_name);

  return true;
}

bool Resolver::Constructor(ast::ConstructorExpression* expr) {
  if (auto* type_ctor = expr->As<ast::TypeConstructorExpression>()) {
    for (auto* value : type_ctor->values()) {
      Mark(value);
      if (!Expression(value)) {
        return false;
      }
    }

    auto* type = Type(type_ctor->type());
    if (!type) {
      return false;
    }

    SetType(expr, type, type_ctor->type()->FriendlyName(builder_->Symbols()));

    // 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.html#type-constructor-expr.
    if (type->Is<sem::Pointer>()) {
      AddError("cannot cast to a pointer", expr->source());
      return false;
    }
    if (auto* vec_type = type->As<sem::Vector>()) {
      return ValidateVectorConstructor(type_ctor, vec_type);
    }
    if (auto* mat_type = type->As<sem::Matrix>()) {
      return ValidateMatrixConstructor(type_ctor, mat_type);
    }
    if (type->is_scalar()) {
      return ValidateScalarConstructor(type_ctor, type);
    }
    if (auto* arr_type = type->As<sem::Array>()) {
      return ValidateArrayConstructor(type_ctor, arr_type);
    }
  } else if (auto* scalar_ctor = expr->As<ast::ScalarConstructorExpression>()) {
    Mark(scalar_ctor->literal());
    auto* type = TypeOf(scalar_ctor->literal());
    if (!type) {
      return false;
    }
    SetType(expr, type);
  } else {
    TINT_ICE(Resolver, diagnostics_)
        << "unexpected constructor expression type";
  }
  return true;
}

bool Resolver::ValidateArrayConstructor(
    const ast::TypeConstructorExpression* ctor,
    const sem::Array* array_type) {
  auto& values = ctor->values();
  auto* elem_type = array_type->ElemType();
  for (auto* value : values) {
    auto* value_type = TypeOf(value)->UnwrapRef();
    if (value_type != elem_type) {
      AddError(
          "type in array constructor does not match array type: "
          "expected '" +
              elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
              TypeNameOf(value) + "'",
          value->source());
      return false;
    }
  }

  if (array_type->IsRuntimeSized()) {
    AddError("cannot init a runtime-sized array", ctor->source());
    return false;
  } else if (!values.empty() && (values.size() != array_type->Count())) {
    std::string fm = values.size() < array_type->Count() ? "few" : "many";
    AddError("array constructor has too " + fm + " elements: expected " +
                 std::to_string(array_type->Count()) + ", found " +
                 std::to_string(values.size()),
             ctor->source());
    return false;
  } else if (values.size() > array_type->Count()) {
    AddError("array constructor has too many elements: expected " +
                 std::to_string(array_type->Count()) + ", found " +
                 std::to_string(values.size()),
             ctor->source());
    return false;
  }
  return true;
}

bool Resolver::ValidateVectorConstructor(
    const ast::TypeConstructorExpression* ctor,
    const sem::Vector* vec_type) {
  auto& values = ctor->values();
  auto* elem_type = vec_type->type();
  size_t value_cardinality_sum = 0;
  for (auto* value : values) {
    auto* value_type = TypeOf(value)->UnwrapRef();
    if (value_type->is_scalar()) {
      if (elem_type != value_type) {
        AddError(
            "type in vector constructor does not match vector type: "
            "expected '" +
                elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
                TypeNameOf(value) + "'",
            value->source());
        return false;
      }

      value_cardinality_sum++;
    } else if (auto* value_vec = value_type->As<sem::Vector>()) {
      auto* value_elem_type = value_vec->type();
      // A mismatch of vector type parameter T is only an error if multiple
      // arguments are present. A single argument constructor constitutes a
      // type conversion expression.
      // NOTE: A conversion expression from a vec<bool> to any other vecN<T>
      // is disallowed (see
      // https://gpuweb.github.io/gpuweb/wgsl.html#conversion-expr).
      if (elem_type != value_elem_type &&
          (values.size() > 1u || value_vec->is_bool_vector())) {
        AddError(
            "type in vector constructor does not match vector type: "
            "expected '" +
                elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
                value_elem_type->FriendlyName(builder_->Symbols()) + "'",
            value->source());
        return false;
      }

      value_cardinality_sum += value_vec->size();
    } else {
      // A vector constructor can only accept vectors and scalars.
      AddError("expected vector or scalar type in vector constructor; found: " +
                   value_type->FriendlyName(builder_->Symbols()),
               value->source());
      return false;
    }
  }

  // A correct vector constructor must either be a zero-value expression,
  // a single-value initializer (splat) expression, or the number of components
  // of all constructor arguments must add up to the vector cardinality.
  if (value_cardinality_sum > 1 && value_cardinality_sum != vec_type->size()) {
    if (values.empty()) {
      TINT_ICE(Resolver, diagnostics_)
          << "constructor arguments expected to be non-empty!";
    }
    const Source& values_start = values[0]->source();
    const Source& values_end = values[values.size() - 1]->source();
    AddError("attempted to construct '" + TypeNameOf(ctor) + "' with " +
                 std::to_string(value_cardinality_sum) + " component(s)",
             Source::Combine(values_start, values_end));
    return false;
  }
  return true;
}

bool Resolver::ValidateMatrix(const sem::Matrix* matrix_type,
                              const Source& source) {
  if (!matrix_type->is_float_matrix()) {
    AddError("matrix element type must be 'f32'", source);
    return false;
  }
  return true;
}  // namespace resolver

bool Resolver::ValidateMatrixConstructor(
    const ast::TypeConstructorExpression* ctor,
    const sem::Matrix* matrix_type) {
  auto& values = ctor->values();
  // Zero Value expression
  if (values.empty()) {
    return true;
  }

  if (!ValidateMatrix(matrix_type, ctor->source())) {
    return false;
  }

  auto* elem_type = matrix_type->type();
  if (matrix_type->columns() != values.size()) {
    const Source& values_start = values[0]->source();
    const Source& values_end = values[values.size() - 1]->source();
    AddError("expected " + std::to_string(matrix_type->columns()) + " '" +
                 VectorPretty(matrix_type->rows(), elem_type) +
                 "' arguments in '" + TypeNameOf(ctor) +
                 "' constructor, found " + std::to_string(values.size()),
             Source::Combine(values_start, values_end));
    return false;
  }

  for (auto* value : values) {
    auto* value_type = TypeOf(value)->UnwrapRef();
    auto* value_vec = value_type->As<sem::Vector>();

    if (!value_vec || value_vec->size() != matrix_type->rows() ||
        elem_type != value_vec->type()) {
      AddError("expected argument type '" +
                   VectorPretty(matrix_type->rows(), elem_type) + "' in '" +
                   TypeNameOf(ctor) + "' constructor, found '" +
                   TypeNameOf(value) + "'",
               value->source());
      return false;
    }
  }

  return true;
}

bool Resolver::ValidateScalarConstructor(
    const ast::TypeConstructorExpression* ctor,
    const sem::Type* type) {
  if (ctor->values().size() == 0) {
    return true;
  }
  if (ctor->values().size() > 1) {
    AddError("expected zero or one value in constructor, got " +
                 std::to_string(ctor->values().size()),
             ctor->source());
    return false;
  }

  // Validate constructor
  auto* value = ctor->values()[0];
  auto* value_type = TypeOf(value)->UnwrapRef();

  using Bool = sem::Bool;
  using I32 = sem::I32;
  using U32 = sem::U32;
  using F32 = sem::F32;

  const bool is_valid =
      (type->Is<Bool>() && value_type->IsAnyOf<Bool, I32, U32, F32>()) ||
      (type->Is<I32>() && value_type->IsAnyOf<I32, U32, F32>()) ||
      (type->Is<U32>() && value_type->IsAnyOf<I32, U32, F32>()) ||
      (type->Is<F32>() && value_type->IsAnyOf<I32, U32, F32>());
  if (!is_valid) {
    AddError("cannot construct '" + TypeNameOf(ctor) +
                 "' with a value of type '" + TypeNameOf(value) + "'",
             ctor->source());

    return false;
  }

  return true;
}

bool Resolver::Identifier(ast::IdentifierExpression* expr) {
  auto symbol = expr->symbol();
  VariableInfo* var;
  if (variable_stack_.get(symbol, &var)) {
    SetType(expr, var->type, var->type_name);

    var->users.push_back(expr);
    set_referenced_from_function_if_needed(var, true);

    if (current_block_) {
      // 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_block_
                  ->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
        auto* loop_block =
            continuing_block->FindFirstParent<sem::LoopBlockStatement>();
        if (loop_block->FirstContinue() != size_t(~0)) {
          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->FirstContinue()) {
              AddError("continue statement bypasses declaration of '" +
                           builder_->Symbols().NameFor(symbol) +
                           "' in continuing block",
                       expr->source());
              return false;
            }
          }
        }
      }
    }

    return true;
  }

  auto iter = symbol_to_function_.find(symbol);
  if (iter != symbol_to_function_.end()) {
    AddError("missing '(' for function call", expr->source().End());
    return false;
  }

  std::string name = builder_->Symbols().NameFor(symbol);
  if (sem::ParseIntrinsicType(name) != IntrinsicType::kNone) {
    AddError("missing '(' for intrinsic call", expr->source().End());
    return false;
  }

  AddError("v-0006: identifier must be declared before use: " + name,
           expr->source());
  return false;
}

bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
  Mark(expr->structure());
  if (!Expression(expr->structure())) {
    return false;
  }

  auto* structure = TypeOf(expr->structure());
  auto* storage_type = structure->UnwrapRef();

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

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

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

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

    // 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());
    }

    builder_->Sem().Add(expr, builder_->create<sem::StructMemberAccess>(
                                  expr, ret, current_statement_, member));
  } else if (auto* vec = storage_type->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 false;
      }

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

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

    // 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 false;
    }

    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));
    }
    builder_->Sem().Add(
        expr, builder_->create<sem::Swizzle>(expr, ret, current_statement_,
                                             std::move(swizzle)));
  } else {
    AddError("invalid use of member accessor on a non-vector/non-struct " +
                 TypeNameOf(expr->structure()),
             expr->source());
    return false;
  }

  SetType(expr, ret);

  return true;
}

bool Resolver::Binary(ast::BinaryExpression* expr) {
  Mark(expr->lhs());
  Mark(expr->rhs());

  if (!Expression(expr->lhs()) || !Expression(expr->rhs())) {
    return false;
  }

  using Bool = sem::Bool;
  using F32 = sem::F32;
  using I32 = sem::I32;
  using U32 = sem::U32;
  using Matrix = sem::Matrix;
  using Vector = sem::Vector;

  auto* lhs_type = const_cast<sem::Type*>(TypeOf(expr->lhs())->UnwrapRef());
  auto* rhs_type = const_cast<sem::Type*>(TypeOf(expr->rhs())->UnwrapRef());

  auto* lhs_vec = lhs_type->As<Vector>();
  auto* lhs_vec_elem_type = lhs_vec ? lhs_vec->type() : nullptr;
  auto* rhs_vec = rhs_type->As<Vector>();
  auto* rhs_vec_elem_type = rhs_vec ? rhs_vec->type() : nullptr;

  const bool matching_vec_elem_types =
      lhs_vec_elem_type && rhs_vec_elem_type &&
      (lhs_vec_elem_type == rhs_vec_elem_type) &&
      (lhs_vec->size() == rhs_vec->size());

  const bool matching_types = matching_vec_elem_types || (lhs_type == rhs_type);

  // Binary logical expressions
  if (expr->IsLogicalAnd() || expr->IsLogicalOr()) {
    if (matching_types && lhs_type->Is<Bool>()) {
      SetType(expr, lhs_type);
      return true;
    }
  }
  if (expr->IsOr() || expr->IsAnd()) {
    if (matching_types && lhs_type->Is<Bool>()) {
      SetType(expr, lhs_type);
      return true;
    }
    if (matching_types && lhs_vec_elem_type && lhs_vec_elem_type->Is<Bool>()) {
      SetType(expr, lhs_type);
      return true;
    }
  }

  // Arithmetic expressions
  if (expr->IsArithmetic()) {
    // Binary arithmetic expressions over scalars
    if (matching_types && lhs_type->is_numeric_scalar()) {
      SetType(expr, lhs_type);
      return true;
    }

    // Binary arithmetic expressions over vectors
    if (matching_types && lhs_vec_elem_type &&
        lhs_vec_elem_type->is_numeric_scalar()) {
      SetType(expr, lhs_type);
      return true;
    }

    // Binary arithmetic expressions with mixed scalar and vector operands
    if (lhs_vec_elem_type && (lhs_vec_elem_type == rhs_type)) {
      if (expr->IsModulo()) {
        if (rhs_type->is_integer_scalar()) {
          SetType(expr, lhs_type);
          return true;
        }
      } else if (rhs_type->is_numeric_scalar()) {
        SetType(expr, lhs_type);
        return true;
      }
    }
    if (rhs_vec_elem_type && (rhs_vec_elem_type == lhs_type)) {
      if (expr->IsModulo()) {
        if (lhs_type->is_integer_scalar()) {
          SetType(expr, rhs_type);
          return true;
        }
      } else if (lhs_type->is_numeric_scalar()) {
        SetType(expr, rhs_type);
        return true;
      }
    }
  }

  // Matrix arithmetic
  auto* lhs_mat = lhs_type->As<Matrix>();
  auto* lhs_mat_elem_type = lhs_mat ? lhs_mat->type() : nullptr;
  auto* rhs_mat = rhs_type->As<Matrix>();
  auto* rhs_mat_elem_type = rhs_mat ? rhs_mat->type() : nullptr;
  // Addition and subtraction of float matrices
  if ((expr->IsAdd() || expr->IsSubtract()) && lhs_mat_elem_type &&
      lhs_mat_elem_type->Is<F32>() && rhs_mat_elem_type &&
      rhs_mat_elem_type->Is<F32>() &&
      (lhs_mat->columns() == rhs_mat->columns()) &&
      (lhs_mat->rows() == rhs_mat->rows())) {
    SetType(expr, rhs_type);
    return true;
  }
  if (expr->IsMultiply()) {
    // Multiplication of a matrix and a scalar
    if (lhs_type->Is<F32>() && rhs_mat_elem_type &&
        rhs_mat_elem_type->Is<F32>()) {
      SetType(expr, rhs_type);
      return true;
    }
    if (lhs_mat_elem_type && lhs_mat_elem_type->Is<F32>() &&
        rhs_type->Is<F32>()) {
      SetType(expr, lhs_type);
      return true;
    }

    // Vector times matrix
    if (lhs_vec_elem_type && lhs_vec_elem_type->Is<F32>() &&
        rhs_mat_elem_type && rhs_mat_elem_type->Is<F32>() &&
        (lhs_vec->size() == rhs_mat->rows())) {
      SetType(expr, builder_->create<sem::Vector>(lhs_vec->type(),
                                                  rhs_mat->columns()));
      return true;
    }

    // Matrix times vector
    if (lhs_mat_elem_type && lhs_mat_elem_type->Is<F32>() &&
        rhs_vec_elem_type && rhs_vec_elem_type->Is<F32>() &&
        (lhs_mat->columns() == rhs_vec->size())) {
      SetType(expr,
              builder_->create<sem::Vector>(rhs_vec->type(), lhs_mat->rows()));
      return true;
    }

    // Matrix times matrix
    if (lhs_mat_elem_type && lhs_mat_elem_type->Is<F32>() &&
        rhs_mat_elem_type && rhs_mat_elem_type->Is<F32>() &&
        (lhs_mat->columns() == rhs_mat->rows())) {
      SetType(expr, builder_->create<sem::Matrix>(
                        builder_->create<sem::Vector>(lhs_mat_elem_type,
                                                      lhs_mat->rows()),
                        rhs_mat->columns()));
      return true;
    }
  }

  // Comparison expressions
  if (expr->IsComparison()) {
    if (matching_types) {
      // Special case for bools: only == and !=
      if (lhs_type->Is<Bool>() && (expr->IsEqual() || expr->IsNotEqual())) {
        SetType(expr, builder_->create<sem::Bool>());
        return true;
      }

      // For the rest, we can compare i32, u32, and f32
      if (lhs_type->IsAnyOf<I32, U32, F32>()) {
        SetType(expr, builder_->create<sem::Bool>());
        return true;
      }
    }

    // Same for vectors
    if (matching_vec_elem_types) {
      if (lhs_vec_elem_type->Is<Bool>() &&
          (expr->IsEqual() || expr->IsNotEqual())) {
        SetType(expr, builder_->create<sem::Vector>(
                          builder_->create<sem::Bool>(), lhs_vec->size()));
        return true;
      }

      if (lhs_vec_elem_type->is_numeric_scalar()) {
        SetType(expr, builder_->create<sem::Vector>(
                          builder_->create<sem::Bool>(), lhs_vec->size()));
        return true;
      }
    }
  }

  // Binary bitwise operations
  if (expr->IsBitwise()) {
    if (matching_types && lhs_type->is_integer_scalar_or_vector()) {
      SetType(expr, lhs_type);
      return true;
    }
  }

  // Bit shift expressions
  if (expr->IsBitshift()) {
    // Type validation rules are the same for left or right shift, despite
    // differences in computation rules (i.e. right shift can be arithmetic or
    // logical depending on lhs type).

    if (lhs_type->IsAnyOf<I32, U32>() && rhs_type->Is<U32>()) {
      SetType(expr, lhs_type);
      return true;
    }

    if (lhs_vec_elem_type && lhs_vec_elem_type->IsAnyOf<I32, U32>() &&
        rhs_vec_elem_type && rhs_vec_elem_type->Is<U32>()) {
      SetType(expr, lhs_type);
      return true;
    }
  }

  AddError("Binary expression operand types are invalid for this operation: " +
               lhs_type->FriendlyName(builder_->Symbols()) + " " +
               FriendlyName(expr->op()) + " " +
               rhs_type->FriendlyName(builder_->Symbols()),
           expr->source());
  return false;
}

bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) {
  Mark(unary->expr());

  // Resolve the inner expression
  if (!Expression(unary->expr())) {
    return false;
  }

  auto* expr_type = TypeOf(unary->expr());
  if (!expr_type) {
    return false;
  }

  std::string type_name;
  const sem::Type* type = nullptr;

  switch (unary->op()) {
    case ast::UnaryOp::kNot:
      // Result type matches the deref'd inner type.
      type_name = TypeNameOf(unary->expr());
      type = expr_type->UnwrapRef();
      if (!type->Is<sem::Bool>() && !type->is_bool_vector()) {
        AddError("cannot logical negate expression of type '" +
                     TypeNameOf(unary->expr()),
                 unary->expr()->source());
        return false;
      }
      break;

    case ast::UnaryOp::kComplement:
      // Result type matches the deref'd inner type.
      type_name = TypeNameOf(unary->expr());
      type = expr_type->UnwrapRef();
      if (!type->is_integer_scalar_or_vector()) {
        AddError("cannot bitwise complement expression of type '" +
                     TypeNameOf(unary->expr()),
                 unary->expr()->source());
        return false;
      }
      break;

    case ast::UnaryOp::kNegation:
      // Result type matches the deref'd inner type.
      type_name = TypeNameOf(unary->expr());
      type = expr_type->UnwrapRef();
      if (!(type->IsAnyOf<sem::F32, sem::I32>() ||
            type->is_signed_integer_vector() || type->is_float_vector())) {
        AddError(
            "cannot negate expression of type '" + TypeNameOf(unary->expr()),
            unary->expr()->source());
        return false;
      }
      break;

    case ast::UnaryOp::kAddressOf:
      if (auto* ref = expr_type->As<sem::Reference>()) {
        type = builder_->create<sem::Pointer>(
            ref->StoreType(), ref->StorageClass(), ref->Access());
      } else {
        AddError("cannot take the address of expression",
                 unary->expr()->source());
        return false;
      }
      break;

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

  SetType(unary, type);
  return true;
}

bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
  ast::Variable* var = stmt->variable();
  Mark(var);

  bool is_global = false;
  if (variable_stack_.get(var->symbol(), nullptr, &is_global)) {
    const char* error_code = is_global ? "v-0013" : "v-0014";
    AddError(error_code,
             "redeclared identifier '" +
                 builder_->Symbols().NameFor(var->symbol()) + "'",
             var->source());
    return false;
  }

  auto* info = Variable(var, VariableKind::kLocal);
  if (!info) {
    return false;
  }

  for (auto* deco : var->decorations()) {
    // TODO(bclayton): Validate decorations
    Mark(deco);
  }

  variable_stack_.set(var->symbol(), info);
  current_block_->AddDecl(var);

  if (!ValidateVariable(info)) {
    return false;
  }

  if (!var->is_const()) {
    if (info->storage_class != ast::StorageClass::kFunction &&
        !IsValidationDisabled(var->decorations(),
                              ast::DisabledValidation::kIgnoreStorageClass)) {
      if (info->storage_class != ast::StorageClass::kNone) {
        AddError("function variable has a non-function storage class",
                 stmt->source());
        return false;
      }
      info->storage_class = ast::StorageClass::kFunction;
    }
  }

  if (!ApplyStorageClassUsageToType(info->storage_class, info->type,
                                    var->source())) {
    AddNote("while instantiating variable " +
                builder_->Symbols().NameFor(var->symbol()),
            var->source());
    return false;
  }

  return true;
}

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

  if (!result) {
    return nullptr;
  }

  named_type_info_.emplace(named_type->name(),
                           TypeDeclInfo{named_type, result});

  if (!ValidateTypeDecl(named_type)) {
    return nullptr;
  }

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

bool Resolver::ValidateTypeDecl(const ast::TypeDecl* named_type) const {
  auto iter = named_type_info_.find(named_type->name());
  if (iter == named_type_info_.end()) {
    TINT_ICE(Resolver, diagnostics_)
        << "ValidateTypeDecl called() before TypeDecl()";
  }
  if (iter->second.ast != named_type) {
    AddError("type with the name '" +
                 builder_->Symbols().NameFor(named_type->name()) +
                 "' was already declared",
             named_type->source());
    AddNote("first declared here", iter->second.ast->source());
    return false;
  }
  return true;
}

sem::Type* Resolver::TypeOf(const ast::Expression* expr) {
  auto it = expr_info_.find(expr);
  if (it != expr_info_.end()) {
    return const_cast<sem::Type*>(it->second.type);
  }
  return nullptr;
}

std::string Resolver::TypeNameOf(const ast::Expression* expr) {
  auto it = expr_info_.find(expr);
  if (it != expr_info_.end()) {
    return it->second.type_name;
  }
  return "";
}

sem::Type* Resolver::TypeOf(const ast::Literal* lit) {
  if (lit->Is<ast::SintLiteral>()) {
    return builder_->create<sem::I32>();
  }
  if (lit->Is<ast::UintLiteral>()) {
    return builder_->create<sem::U32>();
  }
  if (lit->Is<ast::FloatLiteral>()) {
    return builder_->create<sem::F32>();
  }
  if (lit->Is<ast::BoolLiteral>()) {
    return builder_->create<sem::Bool>();
  }
  TINT_UNREACHABLE(Resolver, diagnostics_)
      << "Unhandled literal type: " << lit->TypeInfo().name;
  return nullptr;
}

void Resolver::SetType(const ast::Expression* expr, const sem::Type* type) {
  SetType(expr, type, type->FriendlyName(builder_->Symbols()));
}

void Resolver::SetType(const ast::Expression* expr,
                       const sem::Type* type,
                       const std::string& type_name) {
  if (expr_info_.count(expr)) {
    TINT_ICE(Resolver, diagnostics_)
        << "SetType() called twice for the same expression";
  }
  expr_info_.emplace(expr, ExpressionInfo{type, type_name, current_statement_});
}

bool Resolver::ValidatePipelineStages() {
  auto check_workgroup_storage = [&](FunctionInfo* func,
                                     FunctionInfo* entry_point) {
    auto stage = entry_point->declaration->pipeline_stage();
    if (stage != ast::PipelineStage::kCompute) {
      for (auto* var : func->local_referenced_module_vars) {
        if (var->storage_class == ast::StorageClass::kWorkgroup) {
          std::stringstream stage_name;
          stage_name << stage;
          for (auto* user : var->users) {
            auto it = expr_info_.find(user->As<ast::Expression>());
            if (it != expr_info_.end()) {
              if (func->declaration->symbol() ==
                  it->second.statement->Function()->symbol()) {
                AddError("workgroup memory cannot be used by " +
                             stage_name.str() + " pipeline stage",
                         user->source());
                break;
              }
            }
          }
          AddNote("variable is declared here", var->declaration->source());
          if (func != entry_point) {
            TraverseCallChain(entry_point, func, [&](FunctionInfo* f) {
              AddNote(
                  "called by function '" +
                      builder_->Symbols().NameFor(f->declaration->symbol()) +
                      "'",
                  f->declaration->source());
            });
            AddNote("called by entry point '" +
                        builder_->Symbols().NameFor(
                            entry_point->declaration->symbol()) +
                        "'",
                    entry_point->declaration->source());
          }
          return false;
        }
      }
    }
    return true;
  };

  for (auto* entry_point : entry_points_) {
    if (!check_workgroup_storage(entry_point, entry_point)) {
      return false;
    }
    for (auto* func : entry_point->transitive_calls) {
      if (!check_workgroup_storage(func, entry_point)) {
        return false;
      }
    }
  }

  auto check_intrinsic_calls = [&](FunctionInfo* func,
                                   FunctionInfo* entry_point) {
    auto stage = entry_point->declaration->pipeline_stage();
    for (auto& call : func->intrinsic_calls) {
      if (!call.intrinsic->SupportedStages().Contains(stage)) {
        std::stringstream err;
        err << "built-in cannot be used by " << stage << " pipeline stage";
        AddError(err.str(), call.call->source());
        if (func != entry_point) {
          TraverseCallChain(entry_point, func, [&](FunctionInfo* f) {
            AddNote("called by function '" +
                        builder_->Symbols().NameFor(f->declaration->symbol()) +
                        "'",
                    f->declaration->source());
          });
          AddNote("called by entry point '" +
                      builder_->Symbols().NameFor(
                          entry_point->declaration->symbol()) +
                      "'",
                  entry_point->declaration->source());
        }
        return false;
      }
    }
    return true;
  };

  for (auto* entry_point : entry_points_) {
    if (!check_intrinsic_calls(entry_point, entry_point)) {
      return false;
    }
    for (auto* func : entry_point->transitive_calls) {
      if (!check_intrinsic_calls(func, entry_point)) {
        return false;
      }
    }
  }
  return true;
}

template <typename CALLBACK>
void Resolver::TraverseCallChain(FunctionInfo* from,
                                 FunctionInfo* to,
                                 CALLBACK&& callback) const {
  for (auto* f : from->transitive_calls) {
    if (f == to) {
      callback(f);
      return;
    }
    if (f->transitive_calls.contains(to)) {
      TraverseCallChain(f, to, callback);
      callback(f);
      return;
    }
  }
  TINT_ICE(Resolver, diagnostics_)
      << "TraverseCallChain() 'from' does not transitively call 'to'";
}

void Resolver::CreateSemanticNodes() const {
  auto& sem = builder_->Sem();

  // Collate all the 'ancestor_entry_points' - this is a map of function
  // symbol to all the entry points that transitively call the function.
  std::unordered_map<Symbol, std::vector<Symbol>> ancestor_entry_points;
  for (auto* entry_point : entry_points_) {
    for (auto* call : entry_point->transitive_calls) {
      auto& vec = ancestor_entry_points[call->declaration->symbol()];
      vec.emplace_back(entry_point->declaration->symbol());
    }
  }

  // The next pipeline constant ID to try to allocate.
  uint16_t next_constant_id = 0;

  // Create semantic nodes for all ast::Variables
  for (auto it : variable_to_info_) {
    auto* var = it.first;
    auto* info = it.second;

    sem::Variable* sem_var = nullptr;

    if (auto* override_deco =
            ast::GetDecoration<ast::OverrideDecoration>(var->decorations())) {
      // Create a pipeline overridable constant.
      uint16_t constant_id;
      if (override_deco->HasValue()) {
        constant_id = static_cast<uint16_t>(override_deco->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;
      }

      sem_var = builder_->create<sem::Variable>(var, info->type, constant_id);
    } else {
      sem_var =
          builder_->create<sem::Variable>(var, info->type, info->storage_class,
                                          info->access, info->binding_point);
    }

    std::vector<const sem::VariableUser*> users;
    for (auto* user : info->users) {
      // Create semantic node for the identifier expression if necessary
      auto* sem_expr = sem.Get(user);
      if (sem_expr == nullptr) {
        auto* type = expr_info_.at(user).type;
        auto* stmt = expr_info_.at(user).statement;
        auto* sem_user =
            builder_->create<sem::VariableUser>(user, type, stmt, sem_var);
        sem_var->AddUser(sem_user);
        sem.Add(user, sem_user);
      } else {
        auto* sem_user = sem_expr->As<sem::VariableUser>();
        if (!sem_user) {
          TINT_ICE(Resolver, diagnostics_) << "expected sem::VariableUser, got "
                                           << sem_expr->TypeInfo().name;
        }
        sem_var->AddUser(sem_user);
      }
    }
    sem.Add(var, sem_var);
  }

  auto remap_vars = [&sem](const std::vector<VariableInfo*>& in) {
    std::vector<const sem::Variable*> out;
    out.reserve(in.size());
    for (auto* info : in) {
      out.emplace_back(sem.Get(info->declaration));
    }
    return out;
  };

  // Create semantic nodes for all ast::Functions
  std::unordered_map<FunctionInfo*, sem::Function*> func_info_to_sem_func;
  for (auto it : function_to_info_) {
    auto* func = it.first;
    auto* info = it.second;

    auto* sem_func = builder_->create<sem::Function>(
        info->declaration, const_cast<sem::Type*>(info->return_type),
        remap_vars(info->parameters), remap_vars(info->referenced_module_vars),
        remap_vars(info->local_referenced_module_vars), info->return_statements,
        info->callsites, ancestor_entry_points[func->symbol()],
        info->workgroup_size);
    func_info_to_sem_func.emplace(info, sem_func);
    sem.Add(func, sem_func);
  }

  // Create semantic nodes for all ast::CallExpressions
  for (auto it : function_calls_) {
    auto* call = it.first;
    auto info = it.second;
    auto* sem_func = func_info_to_sem_func.at(info.function);
    sem.Add(call, builder_->create<sem::Call>(call, sem_func, info.statement));
  }

  // Create semantic nodes for all remaining expression types
  for (auto it : expr_info_) {
    auto* expr = it.first;
    auto& info = it.second;
    if (sem.Get(expr)) {
      // Expression has already been assigned a semantic node
      continue;
    }
    sem.Add(expr,
            builder_->create<sem::Expression>(
                const_cast<ast::Expression*>(expr), info.type, info.statement));
  }
}

bool Resolver::DefaultAlignAndSize(const sem::Type* ty,
                                   uint32_t& align,
                                   uint32_t& size) {
  static constexpr uint32_t vector_size[] = {
      /* padding */ 0,
      /* padding */ 0,
      /*vec2*/ 8,
      /*vec3*/ 12,
      /*vec4*/ 16,
  };
  static constexpr uint32_t vector_align[] = {
      /* padding */ 0,
      /* padding */ 0,
      /*vec2*/ 8,
      /*vec3*/ 16,
      /*vec4*/ 16,
  };

  if (ty->is_scalar()) {
    // Note: Also captures booleans, but these are not host-shareable.
    align = 4;
    size = 4;
    return true;
  }
  if (auto* vec = ty->As<sem::Vector>()) {
    if (vec->size() < 2 || vec->size() > 4) {
      TINT_UNREACHABLE(Resolver, diagnostics_)
          << "Invalid vector size: vec" << vec->size();
      return false;
    }
    align = vector_align[vec->size()];
    size = vector_size[vec->size()];
    return true;
  }
  if (auto* mat = ty->As<sem::Matrix>()) {
    if (mat->columns() < 2 || mat->columns() > 4 || mat->rows() < 2 ||
        mat->rows() > 4) {
      TINT_UNREACHABLE(Resolver, diagnostics_)
          << "Invalid matrix size: mat" << mat->columns() << "x" << mat->rows();
      return false;
    }
    align = vector_align[mat->rows()];
    size = vector_align[mat->rows()] * mat->columns();
    return true;
  }
  if (auto* s = ty->As<sem::Struct>()) {
    align = s->Align();
    size = s->Size();
    return true;
  }
  if (auto* a = ty->As<sem::Array>()) {
    align = a->Align();
    size = a->SizeInBytes();
    return true;
  }
  if (auto* a = ty->As<sem::Atomic>()) {
    return DefaultAlignAndSize(a->Type(), align, size);
  }
  TINT_UNREACHABLE(Resolver, diagnostics_)
      << "invalid type " << ty->TypeInfo().name;
  return false;
}

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

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

  if (!IsPlain(el_ty)) {  // Check must come before DefaultAlignAndSize()
    AddError(el_ty->FriendlyName(builder_->Symbols()) +
                 " cannot be used as an element type of an array",
             source);
    return nullptr;
  }

  uint32_t el_align = 0;
  uint32_t el_size = 0;
  if (!DefaultAlignAndSize(el_ty, el_align, el_size)) {
    return nullptr;
  }

  if (!ValidateNoDuplicateDecorations(arr->decorations())) {
    return nullptr;
  }

  // Look for explicit stride via [[stride(n)]] decoration
  uint32_t explicit_stride = 0;
  for (auto* deco : arr->decorations()) {
    Mark(deco);
    if (auto* sd = deco->As<ast::StrideDecoration>()) {
      explicit_stride = sd->stride();
      if (!ValidateArrayStrideDecoration(sd, el_size, el_align, source)) {
        return nullptr;
      }
      continue;
    }

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

  // Calculate implicit stride
  auto implicit_stride = utils::RoundUp(el_align, el_size);

  auto stride = explicit_stride ? explicit_stride : implicit_stride;

  // WebGPU requires runtime arrays have at least one element, but the AST
  // records an element count of 0 for it.
  auto size = std::max<uint32_t>(arr->size(), 1) * stride;
  auto* sem = builder_->create<sem::Array>(el_ty, arr->size(), el_align, size,
                                           stride, implicit_stride);

  if (!ValidateArray(sem, source)) {
    return nullptr;
  }

  return sem;
}

bool Resolver::ValidateArray(const sem::Array* arr, const Source& source) {
  auto* el_ty = arr->ElemType();

  if (auto* el_str = el_ty->As<sem::Struct>()) {
    if (el_str->IsBlockDecorated()) {
      // https://gpuweb.github.io/gpuweb/wgsl/#attributes
      // A structure type with the block attribute must not be:
      // * the element type of an array type
      // * the member type in another structure
      AddError(
          "A structure type with a [[block]] decoration cannot be used as an "
          "element of an array",
          source);
      return false;
    }
  }
  return true;
}

bool Resolver::ValidateArrayStrideDecoration(const ast::StrideDecoration* deco,
                                             uint32_t el_size,
                                             uint32_t el_align,
                                             const Source& source) {
  auto stride = deco->stride();
  bool is_valid_stride =
      (stride >= el_size) && (stride >= el_align) && (stride % el_align == 0);
  if (!is_valid_stride) {
    // https://gpuweb.github.io/gpuweb/wgsl/#array-layout-rules
    // Arrays decorated with the stride attribute must have a stride that is
    // at least the size of the element type, and be a multiple of the
    // element type's alignment value.
    AddError(
        "arrays decorated with the stride attribute must have a stride "
        "that is at least the size of the element type, and be a multiple "
        "of the element type's alignment value.",
        source);
    return false;
  }
  return true;
}

bool Resolver::ValidateStructure(const sem::Struct* str) {
  for (auto* member : str->Members()) {
    if (auto* r = member->Type()->As<sem::Array>()) {
      if (r->IsRuntimeSized()) {
        if (member != str->Members().back()) {
          AddError(
              "v-0015",
              "runtime arrays may only appear as the last member of a struct",
              member->Declaration()->source());
          return false;
        }
        if (!str->IsBlockDecorated()) {
          AddError("v-0015",
                   "a struct containing a runtime-sized array "
                   "requires the [[block]] attribute: '" +
                       builder_->Symbols().NameFor(str->Declaration()->name()) +
                       "'",
                   member->Declaration()->source());
          return false;
        }
      }
    }

    for (auto* deco : member->Declaration()->decorations()) {
      if (!(deco->Is<ast::BuiltinDecoration>() ||
            deco->Is<ast::InterpolateDecoration>() ||
            deco->Is<ast::LocationDecoration>() ||
            deco->Is<ast::StructMemberOffsetDecoration>() ||
            deco->Is<ast::StructMemberSizeDecoration>() ||
            deco->Is<ast::StructMemberAlignDecoration>())) {
        AddError("decoration is not valid for structure members",
                 deco->source());
        return false;
      }
      if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
        if (!ValidateBuiltinDecoration(builtin, member->Type())) {
          return false;
        }
      } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
        if (!ValidateInterpolateDecoration(interpolate, member->Type())) {
          return false;
        }
      }
    }

    if (auto* member_struct_type = member->Type()->As<sem::Struct>()) {
      if (auto* member_struct_type_block_decoration =
              ast::GetDecoration<ast::StructBlockDecoration>(
                  member_struct_type->Declaration()->decorations())) {
        AddError("structs must not contain [[block]] decorated struct members",
                 member->Declaration()->source());
        AddNote("see member's struct decoration here",
                member_struct_type_block_decoration->source());
        return false;
      }
    }
  }

  for (auto* deco : str->Declaration()->decorations()) {
    if (!(deco->Is<ast::StructBlockDecoration>())) {
      AddError("decoration is not valid for struct declarations",
               deco->source());
      return false;
    }
  }

  return true;
}

sem::Struct* Resolver::Structure(const ast::Struct* str) {
  if (!ValidateNoDuplicateDecorations(str->decorations())) {
    return nullptr;
  }
  for (auto* deco : str->decorations()) {
    Mark(deco);
  }

  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.
  // TODO(crbug.com/tint/628): Actually implement storage-class validation.
  uint32_t struct_size = 0;
  uint32_t struct_align = 1;

  for (auto* member : str->members()) {
    Mark(member);

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

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

    uint32_t offset = struct_size;
    uint32_t align = 0;
    uint32_t size = 0;
    if (!DefaultAlignAndSize(type, align, size)) {
      return nullptr;
    }

    if (!ValidateNoDuplicateDecorations(member->decorations())) {
      return nullptr;
    }

    bool has_offset_deco = false;
    bool has_align_deco = false;
    bool has_size_deco = false;
    for (auto* deco : member->decorations()) {
      Mark(deco);
      if (auto* o = deco->As<ast::StructMemberOffsetDecoration>()) {
        // Offset decorations 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_deco = true;
      } else if (auto* a = deco->As<ast::StructMemberAlignDecoration>()) {
        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_deco = true;
      } else if (auto* s = deco->As<ast::StructMemberSizeDecoration>()) {
        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_deco = true;
      }
    }

    if (has_offset_deco && (has_align_deco || has_size_deco)) {
      AddError(
          "offset decorations cannot be used with align or size decorations",
          member->source());
      return nullptr;
    }

    offset = utils::RoundUp(align, offset);

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

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

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

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

  // Keep track of atomic members for validation after all usages have been
  // determined.
  for (size_t i = 0; i < sem_members.size(); i++) {
    if (sem_members[i]->Type()->Is<sem::Atomic>()) {
      atomic_members_.emplace_back(StructMember{out, i});
    }
  }

  if (!ValidateStructure(out)) {
    return nullptr;
  }

  return out;
}

bool Resolver::ValidateReturn(const ast::ReturnStatement* ret) {
  auto* func_type = current_function_->return_type;

  auto* ret_type = ret->has_value() ? TypeOf(ret->value())->UnwrapRef()
                                    : builder_->create<sem::Void>();

  if (func_type->UnwrapRef() != ret_type) {
    AddError("v-000y",
             "return statement type must match its function "
             "return type, returned '" +
                 ret_type->FriendlyName(builder_->Symbols()) + "', expected '" +
                 current_function_->return_type_name + "'",
             ret->source());
    return false;
  }

  return true;
}

bool Resolver::Return(ast::ReturnStatement* ret) {
  current_function_->return_statements.push_back(ret);

  if (auto* value = ret->value()) {
    Mark(value);
    if (!Expression(value)) {
      return false;
    }
  }

  // Validate after processing the return value expression so that its type is
  // available for validation.
  return ValidateReturn(ret);
}

bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
  auto* cond_type = TypeOf(s->condition())->UnwrapRef();
  if (!cond_type->is_integer_scalar()) {
    AddError("v-0025",
             "switch statement selector expression must be of a "
             "scalar integer type",
             s->condition()->source());
    return false;
  }

  bool has_default = false;
  std::unordered_set<uint32_t> selector_set;

  for (auto* case_stmt : s->body()) {
    if (case_stmt->IsDefault()) {
      if (has_default) {
        // More than one default clause
        AddError("v-0008",
                 "switch statement must have exactly one default clause",
                 case_stmt->source());
        return false;
      }
      has_default = true;
    }

    for (auto* selector : case_stmt->selectors()) {
      if (cond_type != TypeOf(selector)) {
        AddError("v-0026",
                 "the case selector values must have the same "
                 "type as the selector expression.",
                 case_stmt->source());
        return false;
      }

      auto v = selector->value_as_u32();
      if (selector_set.find(v) != selector_set.end()) {
        AddError("v-0027",
                 "a literal value must not appear more than once in "
                 "the case selectors for a switch statement: '" +
                     builder_->str(selector) + "'",
                 case_stmt->source());
        return false;
      }
      selector_set.emplace(v);
    }
  }

  if (!has_default) {
    // No default clause
    AddError("switch statement must have a default clause", s->source());
    return false;
  }

  if (!s->body().empty()) {
    auto* last_clause = s->body().back()->As<ast::CaseStatement>();
    auto* last_stmt = last_clause->body()->last();
    if (last_stmt && last_stmt->Is<ast::FallthroughStatement>()) {
      AddError("v-0028",
               "a fallthrough statement must not appear as "
               "the last statement in last clause of a switch",
               last_stmt->source());
      return false;
    }
  }

  return true;
}

bool Resolver::Switch(ast::SwitchStatement* s) {
  Mark(s->condition());
  if (!Expression(s->condition())) {
    return false;
  }
  for (auto* case_stmt : s->body()) {
    Mark(case_stmt);

    sem::Statement* sem_statement =
        builder_->create<sem::Statement>(case_stmt, current_statement_);
    builder_->Sem().Add(case_stmt, sem_statement);
    TINT_SCOPED_ASSIGNMENT(current_statement_, sem_statement);
    if (!CaseStatement(case_stmt)) {
      return false;
    }
  }
  if (!ValidateSwitch(s)) {
    return false;
  }
  return true;
}

bool Resolver::Assignment(ast::AssignmentStatement* a) {
  Mark(a->lhs());
  Mark(a->rhs());

  if (!Expression(a->lhs()) || !Expression(a->rhs())) {
    return false;
  }
  return ValidateAssignment(a);
}

bool Resolver::ValidateAssignment(const ast::AssignmentStatement* a) {
  // https://gpuweb.github.io/gpuweb/wgsl/#assignment-statement
  auto const* lhs_type = TypeOf(a->lhs());
  auto const* rhs_type = TypeOf(a->rhs());

  if (auto* ident = a->lhs()->As<ast::IdentifierExpression>()) {
    VariableInfo* var;
    if (variable_stack_.get(ident->symbol(), &var)) {
      if (var->kind == VariableKind::kParameter) {
        AddError("cannot assign to function parameter", a->lhs()->source());
        AddNote("'" + builder_->Symbols().NameFor(ident->symbol()) +
                    "' is declared here:",
                var->declaration->source());
        return false;
      }
      if (var->declaration->is_const()) {
        AddError("cannot assign to const", a->lhs()->source());
        AddNote("'" + builder_->Symbols().NameFor(ident->symbol()) +
                    "' is declared here:",
                var->declaration->source());
        return false;
      }
    }
  }

  auto* lhs_ref = lhs_type->As<sem::Reference>();
  if (!lhs_ref) {
    // LHS is not a reference, so it has no storage.
    AddError("cannot assign to value of type '" + TypeNameOf(a->lhs()) + "'",
             a->lhs()->source());
    return false;
  }

  auto* storage_type = lhs_ref->StoreType();
  auto* value_type = rhs_type->UnwrapRef();  // Implicit load of RHS

  // Value type has to match storage type
  if (storage_type != value_type) {
    AddError("cannot assign '" + TypeNameOf(a->rhs()) + "' to '" +
                 TypeNameOf(a->lhs()) + "'",
             a->source());
    return false;
  }
  if (lhs_ref->Access() == ast::Access::kRead) {
    AddError(
        "cannot store into a read-only type '" + TypeNameOf(a->lhs()) + "'",
        a->source());
    return false;
  }
  return true;
}

bool Resolver::ValidateNoDuplicateDecorations(
    const ast::DecorationList& decorations) {
  std::unordered_map<const TypeInfo*, Source> seen;
  for (auto* d : decorations) {
    auto res = seen.emplace(&d->TypeInfo(), d->source());
    if (!res.second && !d->Is<ast::InternalDecoration>()) {
      AddError("duplicate " + d->name() + " decoration", d->source());
      AddNote("first decoration declared here", res.first->second);
      return false;
    }
  }
  return true;
}

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 "
            << str->FriendlyName(builder_->Symbols()) << "."
            << builder_->Symbols().NameFor(member->Declaration()->symbol());
        AddNote(err.str(), member->Declaration()->source());
        return false;
      }
    }
    return true;
  }

  if (auto* arr = ty->As<sem::Array>()) {
    return ApplyStorageClassUsageToType(
        sc, const_cast<sem::Type*>(arr->ElemType()), usage);
  }

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

  return true;
}

template <typename T>
bool Resolver::GetScalarConstExprValue(ast::Expression* expr, T* result) {
  if (auto* type_constructor = expr->As<ast::TypeConstructorExpression>()) {
    if (type_constructor->values().size() == 0) {
      // Zero-valued constructor.
      *result = static_cast<T>(0);
      return true;
    } else if (type_constructor->values().size() == 1) {
      // Recurse into the constructor argument expression.
      return GetScalarConstExprValue(type_constructor->values()[0], result);
    } else {
      TINT_ICE(Resolver, diagnostics_) << "malformed scalar type constructor";
    }
  } else if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
    // Cast literal to result type.
    if (auto* int_lit = scalar->literal()->As<ast::IntLiteral>()) {
      *result = static_cast<T>(int_lit->value_as_u32());
      return true;
    } else if (auto* float_lit = scalar->literal()->As<ast::FloatLiteral>()) {
      *result = static_cast<T>(float_lit->value());
      return true;
    } else if (auto* bool_lit = scalar->literal()->As<ast::BoolLiteral>()) {
      *result = static_cast<T>(bool_lit->IsTrue());
      return true;
    } else {
      TINT_ICE(Resolver, diagnostics_) << "unhandled scalar constructor";
    }
  } else {
    TINT_ICE(Resolver, diagnostics_) << "unhandled constant expression";
  }

  return false;
}

template <typename F>
bool Resolver::BlockScope(const ast::BlockStatement* block, F&& callback) {
  auto* sem_block = builder_->Sem().Get<sem::BlockStatement>(block);
  if (!sem_block) {
    TINT_ICE(Resolver, diagnostics_)
        << "Resolver::BlockScope() called on a block for "
           "which semantic information is not available";
    return false;
  }
  TINT_SCOPED_ASSIGNMENT(current_block_,
                         const_cast<sem::BlockStatement*>(sem_block));
  variable_stack_.push_scope();
  bool result = callback();
  variable_stack_.pop_scope();
  return result;
}

std::string Resolver::VectorPretty(uint32_t size,
                                   const sem::Type* element_type) {
  sem::Vector vec_type(element_type, size);
  return vec_type.FriendlyName(builder_->Symbols());
}

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

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

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

Resolver::VariableInfo::VariableInfo(const ast::Variable* decl,
                                     sem::Type* ty,
                                     const std::string& tn,
                                     ast::StorageClass sc,
                                     ast::Access ac,
                                     VariableKind k)
    : declaration(decl),
      type(ty),
      type_name(tn),
      storage_class(sc),
      access(ac),
      kind(k) {}

Resolver::VariableInfo::~VariableInfo() = default;

Resolver::FunctionInfo::FunctionInfo(ast::Function* decl) : declaration(decl) {}
Resolver::FunctionInfo::~FunctionInfo() = default;

}  // namespace resolver
}  // namespace tint
