//===- BPF.cpp ------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "TargetInfo.h"

using namespace clang;
using namespace clang::CodeGen;

//===----------------------------------------------------------------------===//
// BPF ABI Implementation
//===----------------------------------------------------------------------===//

namespace {

class BPFABIInfo : public DefaultABIInfo {
public:
  BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}

  // Classify an aggregate (struct/union) used as an argument or a return
  // value. Aggregates that fit in 1 or 2 registers are passed/returned
  // directly, coerced to an integer or a pair of 64-bit integers; larger
  // ones use an indirect reference.
  ABIArgInfo classifyAggregateType(QualType Ty) const {
    uint64_t Bits = getContext().getTypeSize(Ty);
    if (Bits == 0)
      return ABIArgInfo::getIgnore();

    // Larger aggregates use an indirect reference.
    if (Bits > 128)
      return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());

    // If the aggregate needs 1 or 2 registers, do not use reference.
    llvm::Type *CoerceTy;
    if (Bits <= 64) {
      CoerceTy = llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8));
    } else {
      llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), 64);
      CoerceTy = llvm::ArrayType::get(RegTy, 2);
    }
    return ABIArgInfo::getDirect(CoerceTy);
  }

  ABIArgInfo classifyArgumentType(QualType Ty) const {
    Ty = useFirstFieldIfTransparentUnion(Ty);

    if (isAggregateTypeForABI(Ty))
      return classifyAggregateType(Ty);

    if (const auto *ED = Ty->getAsEnumDecl())
      Ty = ED->getIntegerType();

    ASTContext &Context = getContext();
    if (const auto *EIT = Ty->getAs<BitIntType>())
      if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty))
        return getNaturalAlignIndirect(Ty,
                                       getDataLayout().getAllocaAddrSpace());

    return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
                                              : ABIArgInfo::getDirect());
  }

  ABIArgInfo classifyReturnType(QualType RetTy) const {
    if (RetTy->isVoidType())
      return ABIArgInfo::getIgnore();

    if (isAggregateTypeForABI(RetTy))
      return classifyAggregateType(RetTy);

    // Treat an enum type as its underlying type.
    if (const auto *ED = RetTy->getAsEnumDecl())
      RetTy = ED->getIntegerType();

    ASTContext &Context = getContext();
    if (const auto *EIT = RetTy->getAs<BitIntType>())
      if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty))
        return getNaturalAlignIndirect(RetTy,
                                       getDataLayout().getAllocaAddrSpace());

    // Caller will do necessary sign/zero extension.
    return ABIArgInfo::getDirect();
  }

  void computeInfo(CGFunctionInfo &FI) const override {
    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
    for (auto &I : FI.arguments())
      I.info = classifyArgumentType(I.type);
  }

};

class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
public:
  BPFTargetCodeGenInfo(CodeGenTypes &CGT)
      : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {}
};

}

std::unique_ptr<TargetCodeGenInfo>
CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
  return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes());
}
