//===- 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 = llvm::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 llvm::make_unique<NullEnumerator<PDBSymbol>>();

  auto NET = llvm::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; }
