// Copyright 2020 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 "clspv/Option.h"

#include "Layout.h"

using namespace llvm;

namespace {
bool isScalarType(Type *type) {
  return type->isIntegerTy() || type->isFloatingPointTy();
}

uint64_t structAlignment(StructType *type,
                         std::function<uint64_t(Type *)> alignFn) {
  uint64_t maxAlign = 1;
  for (unsigned i = 0; i < type->getStructNumElements(); i++) {
    uint64_t align = alignFn(type->getStructElementType(i));
    maxAlign = std::max(align, maxAlign);
  }
  return maxAlign;
}

uint64_t scalarAlignment(Type *type) {
  // A scalar of size N has a scalar alignment of N.
  if (isScalarType(type)) {
    return type->getScalarSizeInBits() / 8;
  }

  // A vector or matrix type has a scalar alignment equal to that of its
  // component type.
  if (auto vec_type = dyn_cast<VectorType>(type)) {
    return scalarAlignment(vec_type->getElementType());
  }

  // An array type has a scalar alignment equal to that of its element type.
  if (type->isArrayTy()) {
    return scalarAlignment(type->getArrayElementType());
  }

  // A structure has a scalar alignment equal to the largest scalar alignment of
  // any of its members.
  if (type->isStructTy()) {
    return structAlignment(cast<StructType>(type), scalarAlignment);
  }

  llvm_unreachable("Unsupported type");
}

uint64_t baseAlignment(Type *type) {
  // A scalar has a base alignment equal to its scalar alignment.
  if (isScalarType(type)) {
    return scalarAlignment(type);
  }

  if (auto vec_type = dyn_cast<VectorType>(type)) {
    unsigned numElems = vec_type->getElementCount().getKnownMinValue();

    // A two-component vector has a base alignment equal to twice its scalar
    // alignment.
    if (numElems == 2) {
      return 2 * scalarAlignment(type);
    }
    // A three- or four-component vector has a base alignment equal to four
    // times its scalar alignment.
    if ((numElems == 3) || (numElems == 4)) {
      return 4 * scalarAlignment(type);
    }
  }

  // An array has a base alignment equal to the base alignment of its element
  // type.
  if (type->isArrayTy()) {
    return baseAlignment(type->getArrayElementType());
  }

  // A structure has a base alignment equal to the largest base alignment of any
  // of its members.
  if (type->isStructTy()) {
    return structAlignment(cast<StructType>(type), baseAlignment);
  }

  // TODO A row-major matrix of C columns has a base alignment equal to the base
  // alignment of a vector of C matrix components.
  // TODO A column-major matrix has a base alignment equal to the base alignment
  // of the matrix column type.

  llvm_unreachable("Unsupported type");
}

uint64_t extendedAlignment(Type *type) {
  // A scalar, vector or matrix type has an extended alignment equal to its base
  // alignment.
  // TODO matrix type
  if (isScalarType(type) || type->isVectorTy()) {
    return baseAlignment(type);
  }

  // An array or structure type has an extended alignment equal to the largest
  // extended alignment of any of its members, rounded up to a multiple of 16
  if (type->isStructTy()) {
    auto salign = structAlignment(cast<StructType>(type), extendedAlignment);
    return alignTo(salign, 16);
  }

  if (type->isArrayTy()) {
    auto salign = extendedAlignment(type->getArrayElementType());
    return alignTo(salign, 16);
  }

  llvm_unreachable("Unsupported type");
}

uint64_t standardAlignment(Type *type, spv::StorageClass sclass) {
  // If the scalarBlockLayout feature is enabled on the device then every member
  // must be aligned according to its scalar alignment
  if (clspv::Option::ScalarBlockLayout()) {
    return scalarAlignment(type);
  }

  // All vectors must be aligned according to their scalar alignment
  if (type->isVectorTy()) {
    return scalarAlignment(type);
  }

  // If the uniformBufferStandardLayout feature is not enabled on the device,
  // then any member of an OpTypeStruct with a storage class of Uniform and a
  // decoration of Block must be aligned according to its extended alignment.
  if (!clspv::Option::Std430UniformBufferLayout() &&
      sclass == spv::StorageClassUniform) {
    return extendedAlignment(type);
  }

  // Every other member must be aligned according to its base alignment
  return baseAlignment(type);
}

bool improperlyStraddles(const DataLayout &DL, Type *type, unsigned offset) {
  assert(type->isVectorTy());

  auto size = DL.getTypeStoreSize(type);

  // It is a vector with total size less than or equal to 16 bytes, and has
  // Offset decorations placing its first byte at F and its last byte at L,
  // where floor(F / 16) != floor(L / 16).
  if ((size <= 16) && (offset % 16 + size > 16)) {
    return true;
  }

  // It is a vector with total size greater than 16 bytes and has its Offset
  // decorations placing its first byte at a non-integer multiple of 16
  if ((size > 16) && (offset % 16 != 0)) {
    return true;
  }

  return false;
}
} // namespace

namespace clspv {

// See 14.5 Shader Resource Interface in Vulkan spec
bool isValidExplicitLayout(Module &M, StructType *STy, unsigned Member,
                           spv::StorageClass SClass, unsigned Offset,
                           unsigned PreviousMemberOffset) {

  auto MemberType = STy->getElementType(Member);
  auto Align = standardAlignment(MemberType, SClass);
  auto &DL = M.getDataLayout();

  // The Offset decoration of any member must be a multiple of its alignment
  if (Offset % Align != 0) {
    return false;
  }

  // TODO Any ArrayStride or MatrixStride decoration must be a multiple of the
  // alignment of the array or matrix as defined above

  if (!clspv::Option::ScalarBlockLayout()) {
    // Vectors must not improperly straddle, as defined above
    if (MemberType->isVectorTy() &&
        improperlyStraddles(DL, MemberType, Offset)) {
      return true;
    }

    // The Offset decoration of a member must not place it between the end
    // of a structure or an array and the next multiple of the alignment of that
    // structure or array
    if (Member > 0) {
      auto PType = STy->getElementType(Member - 1);
      if (PType->isStructTy() || PType->isArrayTy()) {
        auto PAlign = standardAlignment(PType, SClass);
        if (Offset - PreviousMemberOffset < PAlign) {
          return false;
        }
      }
    }
  }

  return true;
}

bool isValidExplicitLayout(llvm::Module &M, llvm::StructType *STy,
                           spv::StorageClass SClass) {
  auto const &DL = M.getDataLayout();
  const auto StructLayout = DL.getStructLayout(STy);
  bool ok = true;
  auto previous_offset = 0;
  for (unsigned i = 0; ok && i < STy->getNumElements(); i++) {
    auto offset = StructLayout->getElementOffset(i);
    ok &= isValidExplicitLayout(M, STy, i, SClass, offset, previous_offset);
    previous_offset = offset;
  }

  return ok;
}
} // namespace clspv
