// Copyright 2018-2021 The Clspv Authors. All rights reserved.
//
// 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 "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"

#include "llvm/Support/Debug.h"

#include "clspv/Option.h"

#include "FrontendPlugin.h"

#include <unordered_set>

using namespace clang;

namespace {

static uint32_t kClusteredCount = 0;

struct ExtraValidationConsumer final : public ASTConsumer {
private:
  CompilerInstance &Instance;
  llvm::StringRef InFile;

  enum Layout { UBO, SSBO };

  enum CustomDiagnosticType {
    CustomDiagnosticVectorsMoreThan4Elements,
    CustomDiagnosticVoidPointer,
    CustomDiagnosticUnalignedScalar,
    CustomDiagnosticUnalignedVec2,
    CustomDiagnosticUnalignedVec4,
    CustomDiagnosticUBOUnalignedArray,
    CustomDiagnosticUBOUnalignedStruct,
    CustomDiagnosticSmallStraddle,
    CustomDiagnosticLargeStraddle,
    CustomDiagnosticUnalignedStructMember,
    CustomDiagnosticUBORestrictedSize,
    CustomDiagnosticUBORestrictedStruct,
    CustomDiagnosticUBOArrayStride,
    CustomDiagnosticLocationInfo,
    CustomDiagnosticSSBOUnalignedArray,
    CustomDiagnosticSSBOUnalignedStruct,
    CustomDiagnosticOverloadedKernel,
    CustomDiagnosticStructContainsPointer,
    CustomDiagnosticRecursiveStruct,
    CustomDiagnosticPushConstantSizeExceeded,
    CustomDiagnosticPushConstantContainsArray,
    CustomDiagnosticUnsupported16BitStorage,
    CustomDiagnosticUnsupported8BitStorage,
    CustomDiagnosticTotal
  };
  std::vector<unsigned> CustomDiagnosticsIDMap;

  clspv::Option::StorageClass ConvertToStorageClass(clang::LangAS aspace) {
    switch (aspace) {
    case LangAS::opencl_constant:
      if (clspv::Option::ConstantArgsInUniformBuffer()) {
        return clspv::Option::StorageClass::kUBO;
      } else {
        return clspv::Option::StorageClass::kSSBO;
      }
    case LangAS::opencl_global:
    default:
      return clspv::Option::StorageClass::kSSBO;
    }
  }

  bool ContainsSizedType(QualType QT, uint32_t width) {
    auto canonical = QT.getCanonicalType();
    if (auto *BT = dyn_cast<BuiltinType>(canonical)) {
      switch (BT->getKind()) {
      case BuiltinType::UShort:
      case BuiltinType::Short:
      case BuiltinType::Half:
      case BuiltinType::Float16:
        return width == 16;
      case BuiltinType::UChar:
      case BuiltinType::Char_U:
      case BuiltinType::SChar:
      case BuiltinType::Char_S:
        return width == 8;
      default:
        return false;
      }
    } else if (auto *PT = dyn_cast<PointerType>(canonical)) {
      return ContainsSizedType(PT->getPointeeType(), width);
    } else if (auto *AT = dyn_cast<ArrayType>(canonical)) {
      return ContainsSizedType(AT->getElementType(), width);
    } else if (auto *VT = dyn_cast<VectorType>(canonical)) {
      return ContainsSizedType(VT->getElementType(), width);
    } else if (auto *RT = dyn_cast<RecordType>(canonical)) {
      for (auto field_decl : RT->getDecl()->fields()) {
        if (ContainsSizedType(field_decl->getType(), width))
          return true;
      }
    }

    return false;
  }

  bool ContainsPointerType(QualType QT) {
    auto canonical = QT.getCanonicalType();
    if (canonical->isPointerType()) {
      return true;
    } else if (auto *AT = dyn_cast<ArrayType>(canonical)) {
      return ContainsPointerType(AT->getElementType());
    } else if (auto *RT = dyn_cast<RecordType>(canonical)) {
      for (auto field_decl : RT->getDecl()->fields()) {
        if (ContainsPointerType(field_decl->getType()))
          return true;
      }
    }

    return false;
  }

  bool ContainsArrayType(QualType QT) {
    auto canonical = QT.getCanonicalType();
    if (auto *PT = dyn_cast<PointerType>(canonical)) {
      return ContainsArrayType(PT->getPointeeType());
    } else if (isa<ArrayType>(canonical)) {
      return true;
    } else if (auto *RT = dyn_cast<RecordType>(canonical)) {
      for (auto field_decl : RT->getDecl()->fields()) {
        if (ContainsArrayType(field_decl->getType()))
          return true;
      }
    }

    return false;
  }

  bool IsRecursiveType(QualType QT, llvm::DenseSet<const Type *> *seen) {
    auto canonical = QT.getCanonicalType();
    if (canonical->isRecordType() &&
        !seen->insert(canonical.getTypePtr()).second) {
      return true;
    }

    if (auto *PT = dyn_cast<PointerType>(canonical)) {
      return IsRecursiveType(PT->getPointeeType(), seen);
    } else if (auto *AT = dyn_cast<ArrayType>(canonical)) {
      return IsRecursiveType(AT->getElementType(), seen);
    } else if (auto *RT = dyn_cast<RecordType>(canonical)) {
      for (auto field_decl : RT->getDecl()->fields()) {
        if (IsRecursiveType(field_decl->getType(), seen))
          return true;
      }
    }

    seen->erase(canonical.getTypePtr());
    return false;
  }

  bool IsSupportedType(QualType QT, SourceRange SR, bool IsKernelParameter) {
    auto *Ty = QT.getTypePtr();

    // First check if we have a pointer type.
    if (Ty->isPointerType()) {
      const Type *pointeeTy = Ty->getPointeeType().getTypePtr();
      if (pointeeTy && pointeeTy->isVoidType()) {
        // We don't support void pointers.
        Instance.getDiagnostics().Report(
            SR.getBegin(), CustomDiagnosticsIDMap[CustomDiagnosticVoidPointer]);
        return false;
      }
      // Otherwise check recursively.
      return IsSupportedType(Ty->getPointeeType(), SR, IsKernelParameter);
    }

    const auto &canonicalType = QT.getCanonicalType();
    if (auto *VT = llvm::dyn_cast<ExtVectorType>(canonicalType)) {
      // We don't support vectors with more than 4 elements under all
      // circumstances.
      if (4 < VT->getNumElements() && !clspv::Option::LongVectorSupport()) {
        Report(CustomDiagnosticVectorsMoreThan4Elements, SR, SR);
        return false;
      }

      return true;
    }

    if (auto *RT = llvm::dyn_cast<RecordType>(canonicalType)) {
      // Do not allow recursive struct definitions.
      llvm::DenseSet<const Type *> seen;
      if (IsRecursiveType(canonicalType, &seen)) {
        Instance.getDiagnostics().Report(
            SR.getBegin(),
            CustomDiagnosticsIDMap[CustomDiagnosticRecursiveStruct]);
        return false;
      }

      // To avoid infinite recursion, first verify that the record is not
      // recursive and then that its fields are supported.
      for (auto *field_decl : RT->getDecl()->fields()) {
        if (!IsSupportedType(field_decl->getType(), SR, IsKernelParameter)) {
          return false;
        }
      }

      return true;
    }

    if (auto *AT = llvm::dyn_cast<ArrayType>(canonicalType)) {
      return IsSupportedType(AT->getElementType(), SR, IsKernelParameter);
    }

    // For function prototypes, recurse on return type and parameter types.
    if (auto *FT = llvm::dyn_cast<FunctionProtoType>(canonicalType)) {
      IsKernelParameter =
          IsKernelParameter || (FT->getCallConv() == CC_OpenCLKernel);
      for (auto param : FT->getParamTypes()) {
        if (!IsSupportedType(param, SR, IsKernelParameter)) {
          return false;
        }
      }

      if (!IsSupportedType(FT->getReturnType(), SR, IsKernelParameter)) {
        return false;
      }

      return true;
    }

    if (QT->isBuiltinType()) {
      return true;
    }

    if (QT->isAtomicType()) {
      return true;
    }

#ifndef NDEBUG
    llvm::dbgs() << "IsSupportedType lacks support for QualType: "
                 << QT.getAsString() << '\n';
#endif
    llvm_unreachable("Type not covered by IsSupportedType.");
  }

  // Report a diagnostic using |diag|. If |arg_range| and |specific_range|
  // differ, also issue a note with the specific location of the error.
  void Report(const CustomDiagnosticType &diag, SourceRange arg_range,
              SourceRange specific_range) {
    Instance.getDiagnostics().Report(arg_range.getBegin(),
                                     CustomDiagnosticsIDMap[diag]);
    if (arg_range != specific_range) {
      Instance.getDiagnostics().Report(
          specific_range.getBegin(),
          CustomDiagnosticsIDMap[CustomDiagnosticLocationInfo]);
    }
  }

  // Returns the alignment of |QT| to satisfy |layout|'s rules.
  uint64_t GetAlignment(const QualType QT, const Layout &layout,
                        const ASTContext &context) const {
    const auto canonical = QT.getCanonicalType();
    uint64_t alignment = context.getTypeAlignInChars(canonical).getQuantity();
    if (layout == UBO &&
        (canonical->isRecordType() || canonical->isArrayType())) {
      return llvm::alignTo(alignment, 16);
    }
    return alignment;
  }

  // Returns true if |QT| is a valid layout for a Uniform buffer. Refer to
  // 14.5.4 in the Vulkan specification.
  bool IsSupportedLayout(QualType QT, uint64_t offset, const Layout &layout,
                         ASTContext &context, SourceRange arg_range,
                         SourceRange specific_range) {
    const auto canonical = QT.getCanonicalType();
    if (canonical->isScalarType()) {
      if (!IsSupportedScalarLayout(canonical, offset, layout, context,
                                   arg_range, specific_range))
        return false;
    } else if (canonical->isExtVectorType()) {
      if (!IsSupportedVectorLayout(canonical, offset, layout, context,
                                   arg_range, specific_range))
        return false;
    } else if (canonical->isArrayType()) {
      if (!IsSupportedArrayLayout(canonical, offset, layout, context, arg_range,
                                  specific_range))
        return false;
    } else if (canonical->isRecordType()) {
      if (!IsSupportedRecordLayout(canonical, offset, layout, context,
                                   arg_range, specific_range))
        return false;
    }

    // TODO(alan-baker): Find a way to avoid this restriction.
    // Don't allow padding. This prevents structs like:
    // struct {
    //   int x[2];
    //   int y __attribute((aligned(16)));
    // };
    //
    // This would map in LLVM to { [2 x i32], [8 x i8], i32, [12 xi8] }.
    // There is no easy way to manipulate the padding after the array to
    // satisfy the standard Uniform buffer layout rules in this case. The usual
    // trick is replacing the i8 arrays with an i32 element, but the i32 would
    // still be laid out too close to the array.
    const auto type_size = context.getTypeSizeInChars(canonical).getQuantity();
    const auto type_align = GetAlignment(canonical, layout, context);
    if (layout == UBO && (type_size % type_align != 0)) {
      Report(CustomDiagnosticUBORestrictedSize, arg_range, specific_range);
      return false;
    }

    return true;
  }

  bool IsSupportedScalarLayout(QualType QT, uint64_t offset,
                               const Layout & /*layout*/, ASTContext &context,
                               SourceRange arg_range,
                               SourceRange specific_range) {
    // A scalar type of size N has a base alignment on N.
    const unsigned type_size = context.getTypeSizeInChars(QT).getQuantity();
    if (offset % type_size != 0) {
      Report(CustomDiagnosticUnalignedScalar, arg_range, specific_range);
      return false;
    }

    return true;
  }

  bool IsSupportedVectorLayout(QualType QT, uint64_t offset,
                               const Layout &layout, ASTContext &context,
                               SourceRange arg_range,
                               SourceRange specific_range) {
    // 2-component vectors have a base alignment of 2 * (size of element).
    // 3- and 4-component vectors hae a base alignment of 4 * (size of
    // element).
    const auto *VT = llvm::cast<VectorType>(QT);
    const auto ele_size =
        context.getTypeSizeInChars(VT->getElementType()).getQuantity();
    if (VT->getNumElements() == 2) {
      if (offset % (ele_size * 2) != 0) {
        Report(CustomDiagnosticUnalignedVec2, arg_range, specific_range);
        return false;
      }
    } else if (offset % (ele_size * 4) != 0) {
      // Other vector sizes cause errors elsewhere.
      Report(CustomDiagnosticUnalignedVec4, arg_range, specific_range);
      return false;
    }

    // Straddling rules:
    // * If total vector size is less than 16 bytes, the offset must place the
    // entire vector within the same 16 bytes.
    // * If total vector size is greater than 16 bytes, the offset must be a
    // multiple of 16.
    const auto size = context.getTypeSizeInChars(QT).getQuantity();
    if (size <= 16 && (offset / 16 != (offset + size - 1) / 16)) {
      Report(CustomDiagnosticSmallStraddle, arg_range, specific_range);
      return false;
    } else if (size > 16 && (offset % 16 != 0)) {
      Report(CustomDiagnosticLargeStraddle, arg_range, specific_range);
      return false;
    }

    return IsSupportedLayout(VT->getElementType(), offset, layout, context,
                             arg_range, specific_range);
  }

  bool IsSupportedArrayLayout(QualType QT, uint64_t offset,
                              const Layout &layout, ASTContext &context,
                              SourceRange arg_range,
                              SourceRange specific_range) {
    // An array has a base alignment of is element type.
    // If the layout is UBO, the alignment is rounded up to a multiple of 16.
    const auto *AT = llvm::cast<ArrayType>(QT);
    const auto element_align =
        GetAlignment(AT->getElementType(), layout, context);
    const auto type_align =
        layout == UBO ? llvm::alignTo(element_align, 16) : element_align;
    if (offset % type_align != 0) {
      auto diag_id = layout == UBO ? CustomDiagnosticUBOUnalignedArray
                                   : CustomDiagnosticSSBOUnalignedArray;
      Report(diag_id, arg_range, specific_range);
      return false;
    }
    if (layout == UBO && !clspv::Option::RelaxedUniformBufferLayout()) {
      // The ArrayStride must be a multiple of the base alignment of the array
      // (i.e. a multiple of 16).  This means that the element size must be
      // restricted to be the base alignment of the array.
      const auto element_size =
          context.getTypeSizeInChars(AT->getElementType()).getQuantity();
      if (element_size % type_align != 0) {
        Report(CustomDiagnosticUBOArrayStride, arg_range, specific_range);
        return false;
      }
    }

    return IsSupportedLayout(AT->getElementType(), offset, layout, context,
                             arg_range, specific_range);
  }

  bool IsSupportedRecordLayout(QualType QT, uint64_t offset,
                               const Layout &layout, ASTContext &context,
                               SourceRange arg_range,
                               SourceRange specific_range) {
    // A structure has a base alignment of its largest member. For UBO layouts,
    // alignment is rounded up to a multiple of 16.
    const auto *RT = llvm::cast<RecordType>(QT);
    auto type_alignment = GetAlignment(QT, layout, context);
    if (layout == UBO)
      llvm::alignTo(type_alignment, 16);
    if (offset % type_alignment != 0) {
      auto diag_id = layout == UBO ? CustomDiagnosticUBOUnalignedStruct
                                   : CustomDiagnosticSSBOUnalignedStruct;
      Report(diag_id, arg_range, specific_range);
      return false;
    }

    const auto &record_layout = context.getASTRecordLayout(RT->getDecl());
    const FieldDecl *prev = nullptr;
    for (auto field_decl : RT->getDecl()->fields()) {
      const auto field_type = field_decl->getType();
      const unsigned field_no = field_decl->getFieldIndex();
      const uint64_t field_offset =
          record_layout.getFieldOffset(field_no) / context.getCharWidth();

      // Rules must be checked recursively.
      if (!IsSupportedLayout(field_type, field_offset + offset, layout, context,
                             arg_range, field_decl->getSourceRange())) {
        return false;
      }

      if (prev) {
        const auto prev_canonical = prev->getType().getCanonicalType();
        const uint64_t prev_offset =
            record_layout.getFieldOffset(field_no - 1) / context.getCharWidth();
        const auto prev_size =
            context.getTypeSizeInChars(prev_canonical).getQuantity();
        const auto prev_alignment =
            GetAlignment(prev_canonical, layout, context);
        const auto next_available =
            prev_offset + llvm::alignTo(prev_size, prev_alignment);
        if (prev_canonical->isArrayType() || prev_canonical->isRecordType()) {
          // The next element after an array or struct must be placed on or
          // after the next multiple of the alignment of that array or
          // struct.
          // For UBO layouts, both arrays and structs must be aligned to a
          // multiple of 16 bytes.
          const uint64_t final_align = layout == UBO
                                           ? llvm::alignTo(next_available, 16)
                                           : next_available;
          if (final_align > field_offset) {
            Report(CustomDiagnosticUnalignedStructMember, arg_range,
                   field_decl->getSourceRange());
            return false;
          }
        }
      }

      prev = field_decl;
    }

    return true;
  }

  // This will be used to check the inside of function bodies.
  class DeclVisitor : public RecursiveASTVisitor<DeclVisitor> {
  private:
    ExtraValidationConsumer &consumer;

  public:
    explicit DeclVisitor(ExtraValidationConsumer &VC) : consumer(VC) {}

    // Visits a declaration.  Emits a diagnostic and returns false if the
    // declaration represents an unsupported vector value or vector type.
    // Otherwise returns true.
    //
    // Looking at the Decl class hierarchy, it seems ValueDecl and TypeDecl
    // are the only two that might represent an unsupported vector type.
    bool VisitValueDecl(ValueDecl *VD) {
      return consumer.IsSupportedType(VD->getType(), VD->getSourceRange(),
                                      false);
    }
    bool VisitValueDecl(TypeDecl *TD) {
      QualType DefinedType = TD->getASTContext().getTypeDeclType(TD);
      return consumer.IsSupportedType(DefinedType, TD->getSourceRange(), false);
    }
  };

  DeclVisitor Visitor;
  std::unordered_set<std::string> Kernels;

public:
  explicit ExtraValidationConsumer(CompilerInstance &Instance,
                                   llvm::StringRef InFile)
      : Instance(Instance), InFile(InFile),
        CustomDiagnosticsIDMap(CustomDiagnosticTotal), Visitor(*this) {
    auto &DE = Instance.getDiagnostics();

    CustomDiagnosticsIDMap[CustomDiagnosticVectorsMoreThan4Elements] =
        DE.getCustomDiagID(
            DiagnosticsEngine::Error,
            "vectors with more than 4 elements are not supported");
    CustomDiagnosticsIDMap[CustomDiagnosticVoidPointer] = DE.getCustomDiagID(
        DiagnosticsEngine::Error, "pointer-to-void is not supported");
    CustomDiagnosticsIDMap[CustomDiagnosticUnalignedScalar] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "scalar elements must be aligned to their size");
    CustomDiagnosticsIDMap[CustomDiagnosticUnalignedVec2] = DE.getCustomDiagID(
        DiagnosticsEngine::Error,
        "two-component vectors must be aligned to 2 times their element size");
    CustomDiagnosticsIDMap[CustomDiagnosticUnalignedVec4] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "three- and four-component vectors must be aligned "
                           "to 4 times their element size");
    CustomDiagnosticsIDMap[CustomDiagnosticUBOUnalignedArray] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "in an UBO, arrays must be aligned to their element "
                           "alignment, rounded up to a multiple of 16 bytes");
    CustomDiagnosticsIDMap[CustomDiagnosticUBOUnalignedStruct] =
        DE.getCustomDiagID(
            DiagnosticsEngine::Error,
            "in an UBO, structs must be aligned to their "
            "largest element alignment, rounded up to a multiple of "
            "16 bytes");
    CustomDiagnosticsIDMap[CustomDiagnosticSmallStraddle] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "vectors with a total size less than or equal to 16 "
                           "bytes must be placed entirely within a 16 byte "
                           "aligned region");
    CustomDiagnosticsIDMap[CustomDiagnosticLargeStraddle] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "vectors with a total size greater than 16 bytes "
                           "must aligned to 16 bytes");
    CustomDiagnosticsIDMap[CustomDiagnosticUnalignedStructMember] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "a structure member must not be placed between the "
                           "end of a structure or array and the next multiple "
                           "of the base alignment of that structure or array");
    CustomDiagnosticsIDMap[CustomDiagnosticUBORestrictedSize] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "clspv restriction: UBO element size must be a "
                           "multiple of that element's alignment");
    CustomDiagnosticsIDMap[CustomDiagnosticUBORestrictedStruct] =
        DE.getCustomDiagID(
            DiagnosticsEngine::Error,
            "clspv restriction: UBO structures may not have implicit padding");
    CustomDiagnosticsIDMap[CustomDiagnosticUBOArrayStride] = DE.getCustomDiagID(
        DiagnosticsEngine::Error,
        "clspv restriction: to satisfy UBO ArrayStride restrictions, element "
        "size must be a multiple of array alignment");
    CustomDiagnosticsIDMap[CustomDiagnosticLocationInfo] =
        DE.getCustomDiagID(DiagnosticsEngine::Note, "here");
    CustomDiagnosticsIDMap[CustomDiagnosticSSBOUnalignedArray] =
        DE.getCustomDiagID(
            DiagnosticsEngine::Error,
            "in a SSBO, arrays must be aligned to their element alignment");
    CustomDiagnosticsIDMap[CustomDiagnosticSSBOUnalignedStruct] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "in a SSBO, structs must be aligned to their "
                           "largest element alignment");
    CustomDiagnosticsIDMap[CustomDiagnosticOverloadedKernel] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "kernel functions can't be overloaded");
    CustomDiagnosticsIDMap[CustomDiagnosticStructContainsPointer] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "structures may not contain pointers");
    CustomDiagnosticsIDMap[CustomDiagnosticRecursiveStruct] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "recursive structures are not supported");
    CustomDiagnosticsIDMap[CustomDiagnosticPushConstantSizeExceeded] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "max push constant size exceeded");
    CustomDiagnosticsIDMap[CustomDiagnosticPushConstantContainsArray] =
        DE.getCustomDiagID(
            DiagnosticsEngine::Error,
            "arrays are not supported in push constants currently");
    CustomDiagnosticsIDMap[CustomDiagnosticUnsupported16BitStorage] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "16-bit storage is not supported for "
                           "%select{SSBOs|UBOs|push constants}0");
    CustomDiagnosticsIDMap[CustomDiagnosticUnsupported8BitStorage] =
        DE.getCustomDiagID(DiagnosticsEngine::Error,
                           "8-bit storage is not supported for "
                           "%select{SSBOs|UBOs|push constants}0");
  }

  virtual bool HandleTopLevelDecl(DeclGroupRef DG) override {
    for (auto *D : DG) {
      if (auto *FD = llvm::dyn_cast<FunctionDecl>(D)) {
        // If the function has a body it means we are not an OpenCL builtin
        // function.
        if (FD->hasBody()) {
          if (!IsSupportedType(FD->getReturnType(),
                               FD->getReturnTypeSourceRange(), false)) {
            return false;
          }

          bool is_opencl_kernel = false;
          if (FD->hasAttrs()) {
            for (auto *attr : FD->attrs()) {
              if (attr->getKind() == attr::Kind::OpenCLKernel) {
                is_opencl_kernel = true;
              }
            }
          }

          if (is_opencl_kernel) {
            if (Kernels.count(FD->getName().str()) != 0) {
              auto srcRange = FD->getSourceRange();
              Report(CustomDiagnosticOverloadedKernel, srcRange, srcRange);
            } else {
              Kernels.insert(FD->getName().str());
            }
          }

          RecordDecl *clustered_args = nullptr;
          if (is_opencl_kernel && clspv::Option::PodArgsInPushConstants()) {
            clustered_args = FD->getASTContext().buildImplicitRecord(
                "__clspv.clustered_args." + std::to_string(kClusteredCount++));
            clustered_args->startDefinition();
          }
          for (auto *P : FD->parameters()) {
            auto type = P->getType();
            if (!IsSupportedType(P->getOriginalType(), P->getSourceRange(),
                                 is_opencl_kernel)) {
              return false;
            }

            if (is_opencl_kernel && type->isPointerType() &&
                ((type->getPointeeType().getAddressSpace() ==
                  LangAS::opencl_constant) ||
                 (type->getPointeeType().getAddressSpace() ==
                  LangAS::opencl_global))) {
              // The argument will be generated as an array within a block.
              // Generate an array type to check the validity for the generated
              // case.
              Layout layout = SSBO;
              if (clspv::Option::ConstantArgsInUniformBuffer() &&
                  !clspv::Option::Std430UniformBufferLayout() &&
                  type->getPointeeType().getAddressSpace() ==
                      LangAS::opencl_constant) {
                layout = UBO;
              }
              auto array_type = FD->getASTContext().getIncompleteArrayType(
                  type->getPointeeType(), clang::ArrayType::Normal, 0);
              if (!IsSupportedLayout(array_type, 0, layout, FD->getASTContext(),
                                     P->getSourceRange(),
                                     P->getSourceRange())) {
                return false;
              }
            }

            // Check if storage capabilities are supported.
            if (is_opencl_kernel) {
              bool contains_16bit =
                  ContainsSizedType(type.getCanonicalType(), 16);
              bool contains_8bit =
                  ContainsSizedType(type.getCanonicalType(), 8);
              auto sc = clspv::Option::StorageClass::kSSBO;
              if (type->isPointerType()) {
                sc = ConvertToStorageClass(
                    type->getPointeeType().getAddressSpace());
              } else if (clspv::Option::PodArgsInUniformBuffer()) {
                sc = clspv::Option::StorageClass::kUBO;
              } else if (clspv::Option::PodArgsInPushConstants()) {
                sc = clspv::Option::StorageClass::kPushConstant;
              }

              if (type->isPointerType() ||
                  sc != clspv::Option::StorageClass::kSSBO ||
                  !clspv::Option::ClusterPodKernelArgs()) {
                // For clustered pod args, assume we can fall back on
                // type-mangling.
                if (contains_16bit &&
                    !clspv::Option::Supports16BitStorageClass(sc)) {
                  Instance.getDiagnostics().Report(
                      P->getSourceRange().getBegin(),
                      CustomDiagnosticsIDMap
                          [CustomDiagnosticUnsupported16BitStorage])
                      << static_cast<int>(sc);
                }
                if (contains_8bit &&
                    !clspv::Option::Supports8BitStorageClass(sc)) {
                  Instance.getDiagnostics().Report(
                      P->getSourceRange().getBegin(),
                      CustomDiagnosticsIDMap
                          [CustomDiagnosticUnsupported8BitStorage])
                      << static_cast<int>(sc);
                }
              }
            }

            if (is_opencl_kernel && type->isPointerType()) {
              auto pointee_type = type->getPointeeType().getCanonicalType();
              if (ContainsPointerType(pointee_type)) {
                Instance.getDiagnostics().Report(
                    P->getSourceRange().getBegin(),
                    CustomDiagnosticsIDMap
                        [CustomDiagnosticStructContainsPointer]);
                return false;
              }
            }

            if (is_opencl_kernel && !type->isPointerType()) {
              if (clspv::Option::PodArgsInPushConstants()) {
                // Don't allow arrays in push constants currently.
                if (ContainsArrayType(type)) {
                  Report(CustomDiagnosticPushConstantContainsArray,
                         P->getSourceRange(), P->getSourceRange());
                  return false;
                }
                FieldDecl *field_decl = FieldDecl::Create(
                    FD->getASTContext(),
                    Decl::castToDeclContext(clustered_args),
                    P->getSourceRange().getBegin(),
                    P->getSourceRange().getEnd(), P->getIdentifier(),
                    P->getType(), nullptr, nullptr, false, ICIS_NoInit);
                field_decl->setAccess(AS_public);
                clustered_args->addDecl(field_decl);
              } else {
                Layout layout = SSBO;
                if (clspv::Option::PodArgsInUniformBuffer() &&
                    !clspv::Option::Std430UniformBufferLayout())
                  layout = UBO;

                if (!IsSupportedLayout(type, 0, layout, FD->getASTContext(),
                                       P->getSourceRange(),
                                       P->getSourceRange())) {
                  return false;
                }
              }
            }
          }

          if (clustered_args) {
            clustered_args->completeDefinition();
            if (!clustered_args->field_empty()) {
              auto record_type =
                  FD->getASTContext().getRecordType(clustered_args);
              if (!IsSupportedLayout(record_type, 0, SSBO, FD->getASTContext(),
                                     FD->getSourceRange(),
                                     FD->getSourceRange())) {
                return false;
              }

              if (FD->getASTContext()
                      .getTypeSizeInChars(record_type)
                      .getQuantity() > clspv::Option::MaxPushConstantsSize()) {
                Report(CustomDiagnosticPushConstantSizeExceeded,
                       FD->getSourceRange(), FD->getSourceRange());
                return false;
              }
            }
          }

          // Check for unsupported vector types.
          Visitor.TraverseDecl(FD);
        }
      }
    }

    return true;
  }
};
} // namespace

namespace clspv {
std::unique_ptr<ASTConsumer>
ExtraValidationASTAction::CreateASTConsumer(CompilerInstance &CI,
                                            llvm::StringRef InFile) {
  return std::unique_ptr<ASTConsumer>(new ExtraValidationConsumer(CI, InFile));
}
} // namespace clspv
