//===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===//
//
// 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 "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"

#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"

using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;

namespace {
// This is kind of a silly class, hence why we keep it private to the file.
// It's only purpose is to wrap the real type record.  I guess this is so that
// we can have the lexical parent point to the function instead of the global
// scope.
class NativeTypeFunctionArg : public NativeRawSymbol {
public:
  NativeTypeFunctionArg(NativeSession &Session,
                        std::unique_ptr<PDBSymbol> RealType)
      : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0),
        RealType(std::move(RealType)) {}

  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
            PdbSymbolIdField RecurseIdFields) const override {
    NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);

    dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
                      PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
  }

  SymIndexId getTypeId() const override { return RealType->getSymIndexId(); }

  std::unique_ptr<PDBSymbol> RealType;
};

class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> {
public:
  NativeEnumFunctionArgs(NativeSession &Session,
                         std::unique_ptr<NativeEnumTypes> TypeEnumerator)
      : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {}

  uint32_t getChildCount() const override {
    return TypeEnumerator->getChildCount();
  }
  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
    return wrap(TypeEnumerator->getChildAtIndex(Index));
  }
  std::unique_ptr<PDBSymbol> getNext() override {
    return wrap(TypeEnumerator->getNext());
  }

  void reset() override { TypeEnumerator->reset(); }

private:
  std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const {
    if (!S)
      return nullptr;
    auto NTFA = std::make_unique<NativeTypeFunctionArg>(Session, std::move(S));
    return PDBSymbol::create(Session, std::move(NTFA));
  }
  NativeSession &Session;
  std::unique_ptr<NativeEnumTypes> TypeEnumerator;
};
} // namespace

NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session,
                                             SymIndexId Id,
                                             codeview::TypeIndex Index,
                                             codeview::ProcedureRecord Proc)
    : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
      Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {}

NativeTypeFunctionSig::NativeTypeFunctionSig(
    NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index,
    codeview::MemberFunctionRecord MemberFunc)
    : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
      MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {}

void NativeTypeFunctionSig::initialize() {
  if (IsMemberFunction) {
    ClassParentId =
        Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType);
    initializeArgList(MemberFunc.ArgumentList);
  } else {
    initializeArgList(Proc.ArgumentList);
  }
}

NativeTypeFunctionSig::~NativeTypeFunctionSig() {}

void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) {
  TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
  CVType CVT = Tpi.typeCollection().getType(ArgListTI);

  cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList));
}

void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent,
                                 PdbSymbolIdField ShowIdFields,
                                 PdbSymbolIdField RecurseIdFields) const {

  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);

  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
                    PdbSymbolIdField::LexicalParent, ShowIdFields,
                    RecurseIdFields);

  dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent);
  dumpSymbolField(OS, "count", getCount(), Indent);
  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
  if (IsMemberFunction)
    dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent);
  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
  dumpSymbolField(OS, "constType", isConstType(), Indent);
  dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(),
                  Indent);
  dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent);
  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
}

std::unique_ptr<IPDBEnumSymbols>
NativeTypeFunctionSig::findChildren(PDB_SymType Type) const {
  if (Type != PDB_SymType::FunctionArg)
    return std::make_unique<NullEnumerator<PDBSymbol>>();

  auto NET = std::make_unique<NativeEnumTypes>(Session,
                                                /* copy */ ArgList.ArgIndices);
  return std::unique_ptr<IPDBEnumSymbols>(
      new NativeEnumFunctionArgs(Session, std::move(NET)));
}

SymIndexId NativeTypeFunctionSig::getClassParentId() const {
  if (!IsMemberFunction)
    return 0;

  return ClassParentId;
}

PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const {
  return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv;
}

uint32_t NativeTypeFunctionSig::getCount() const {
  return IsMemberFunction ? (1 + MemberFunc.getParameterCount())
                          : Proc.getParameterCount();
}

SymIndexId NativeTypeFunctionSig::getTypeId() const {
  TypeIndex ReturnTI =
      IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType();

  SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI);
  return Result;
}

int32_t NativeTypeFunctionSig::getThisAdjust() const {
  return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0;
}

bool NativeTypeFunctionSig::hasConstructor() const {
  if (!IsMemberFunction)
    return false;

  return (MemberFunc.getOptions() & FunctionOptions::Constructor) !=
         FunctionOptions::None;
}

bool NativeTypeFunctionSig::isConstType() const { return false; }

bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
  if (!IsMemberFunction)
    return false;

  return (MemberFunc.getOptions() &
          FunctionOptions::ConstructorWithVirtualBases) !=
         FunctionOptions::None;
}

bool NativeTypeFunctionSig::isCxxReturnUdt() const {
  FunctionOptions Options =
      IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions();
  return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None;
}

bool NativeTypeFunctionSig::isUnalignedType() const { return false; }

bool NativeTypeFunctionSig::isVolatileType() const { return false; }
