//===--- InterpFrame.cpp - Call Frame implementation for the VM -*- 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 "InterpFrame.h"
#include "Boolean.h"
#include "Char.h"
#include "Function.h"
#include "InterpStack.h"
#include "InterpState.h"
#include "MemberPointer.h"
#include "Pointer.h"
#include "PrimType.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"

using namespace clang;
using namespace clang::interp;

InterpFrame::InterpFrame(InterpState &S)
    : Caller(nullptr), S(S), Func(nullptr), RetPC(CodePtr()), Args(nullptr),
      ArgSize(0), Depth(0) {}

InterpFrame::InterpFrame(InterpState &S, const Function *Func,
                         InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize)
    : Caller(Caller), S(S), Func(Func), RetPC(RetPC),
      Args(static_cast<char *>(S.Stk.top())), ArgSize(ArgSize),
      Depth(Caller ? Caller->Depth + 1 : 0) {
  assert(Func);
#ifndef NDEBUG
  FrameOffset = S.Stk.size();
#endif

  FuncFlags |= Func->hasRVO() * HasRVOFlag;
  FuncFlags |= Func->hasThisPointer() * HasThisFlag;

  // Initialize argument blocks.
  for (unsigned I = 0, N = Func->getNumWrittenParams(); I != N; ++I)
    new (argBlock(I)) Block(S.EvalID, Func->getParamDescriptor(I).Desc);

  if (Func->getFrameSize() == 0)
    return;

  for (auto &Scope : Func->scopes()) {
    for (auto &Local : Scope.locals()) {
      new (localBlock(Local.Offset))
          Block(S.EvalID, Local.Desc, Block::InlineDescMD);
      // Note that we are NOT calling invokeCtor() here, since that is done
      // via the InitScope op.
      new (localInlineDesc(Local.Offset)) InlineDescriptor(Local.Desc);
    }
  }
}

InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC,
                         unsigned VarArgSize)
    : InterpFrame(S, Func, S.Current, RetPC, Func->getArgSize() + VarArgSize) {
  // As per our calling convention, the this pointer is
  // part of the ArgSize.
  // If the function has RVO, the RVO pointer is first.
  // If the fuction has a This pointer, that one is next.
  // Then follow the actual arguments (but those are handled
  // in getParamPointer()).
}

InterpFrame::~InterpFrame() {
  if (!Func)
    return;

  // De-initialize all argument blocks.
  for (unsigned I = 0, N = Func->getNumWrittenParams(); I != N; ++I)
    S.deallocate(argBlock(I));

  // When destroying the InterpFrame, call the Dtor for all blocks
  // that haven't been destroyed via a destroy() op yet.
  // This happens when the execution is interruped midway-through.
  for (auto &Scope : Func->scopes()) {
    for (auto &Local : Scope.locals()) {
      S.deallocate(localBlock(Local.Offset));
    }
  }
}

void InterpFrame::initScope(unsigned Idx) {
  if (!Func)
    return;

  for (auto &Local : Func->getScope(Idx).locals()) {
    assert(!localBlock(Local.Offset)->isInitialized());
    localBlock(Local.Offset)->invokeCtor();
  }
}

void InterpFrame::enableLocal(unsigned Idx) {
  assert(Func);

  // FIXME: This is a little dirty, but to avoid adding a flag to
  // InlineDescriptor that's only ever useful on the toplevel of local
  // variables, we reuse the IsActive flag for the enabled state. We should
  // probably use a different struct than InlineDescriptor for the block-level
  // inline descriptor of local varaibles.
  localInlineDesc(Idx)->IsActive = true;
}

void InterpFrame::destroy(unsigned Idx) {
  for (auto &Local : Func->getScope(Idx).locals_reverse()) {
    S.deallocate(localBlock(Local.Offset));
  }
}

template <typename T>
static void print(llvm::raw_ostream &OS, const T &V, const Context &Ctx,
                  QualType Ty) {
  if constexpr (std::is_same_v<Pointer, T>) {
    if (Ty->isPointerOrReferenceType())
      V.toAPValue(Ctx.getASTContext()).printPretty(OS, Ctx.getASTContext(), Ty);
    else {
      if (std::optional<APValue> RValue = V.toRValue(Ctx, Ty))
        RValue->printPretty(OS, Ctx.getASTContext(), Ty);
      else
        OS << "...";
    }
  } else {
    V.toAPValue(Ctx.getASTContext()).printPretty(OS, Ctx.getASTContext(), Ty);
  }
}

static bool shouldSkipInBacktrace(const Function *F) {
  if (F->isLambdaStaticInvoker())
    return true;

  const FunctionDecl *FD = F->getDecl();
  if (FD->getDeclName().getCXXOverloadedOperator() == OO_New ||
      FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New)
    return true;

  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD);
      MD && MD->getParent()->isAnonymousStructOrUnion())
    return true;

  return false;
}

void InterpFrame::describe(llvm::raw_ostream &OS) const {
  assert(Func);
  // For lambda static invokers, we would just print __invoke().
  if (shouldSkipInBacktrace(Func))
    return;

  const ASTContext &ASTCtx = S.getASTContext();
  const Expr *CallExpr = Caller->getExpr(getRetOpPC());
  const FunctionDecl *F = Func->getDecl();
  auto PrintingPolicy = ASTCtx.getPrintingPolicy();
  PrintingPolicy.SuppressLambdaBody = true;

  bool IsMemberCall = false;
  bool ExplicitInstanceParam = false;
  if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
    IsMemberCall = !isa<CXXConstructorDecl>(MD) && !MD->isStatic();
    ExplicitInstanceParam = MD->isExplicitObjectMemberFunction();
  }

  if (Func->hasThisPointer() && IsMemberCall) {
    if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
      const Expr *Object = MCE->getImplicitObjectArgument();
      Object->printPretty(OS, /*Helper=*/nullptr,
                          PrintingPolicy,
                          /*Indentation=*/0);
      if (Object->getType()->isPointerType())
        OS << "->";
      else
        OS << '.';
    } else if (const auto *OCE =
                   dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
      OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
                                  PrintingPolicy,
                                  /*Indentation=*/0);
      OS << '.';
    } else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) {
      print(OS, getThis(), S.getContext(),
            ASTCtx.getLValueReferenceType(
                ASTCtx.getCanonicalTagType(M->getParent())));
      OS << '.';
    }
  }

  F->getNameForDiagnostic(OS, PrintingPolicy, /*Qualified=*/false);
  OS << '(';
  unsigned Off = 0;
  unsigned ParamIndex = ExplicitInstanceParam;
  Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;
  Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0;
  llvm::ListSeparator Comma;
  for (const ParmVarDecl *Param :
       F->parameters().slice(ExplicitInstanceParam)) {
    OS << Comma;
    PrimType PrimT = Func->getParamDescriptor(ParamIndex).T;
    TYPE_SWITCH(PrimT,
                print(OS, stackRef<T>(Off), S.getContext(), Param->getType()));
    Off += align(primSize(PrimT));
    ++ParamIndex;
  }
  OS << ')';
}

SourceRange InterpFrame::getCallRange() const {
  if (!Caller->Func) {
    if (SourceRange NullRange = S.getSource({}).getRange(); NullRange.isValid())
      return NullRange;

    return S.EvalLocation;
  }

  // Move up to the frame that has a valid location for the caller.
  for (const InterpFrame *C = this; C; C = C->Caller) {
    if (!C->RetPC)
      continue;
    SourceRange CallRange =
        C->Caller->Func->getSource(C->getRetOpPC()).getRange();
    if (CallRange.isValid())
      return CallRange;
  }
  return S.EvalLocation;
}

const FunctionDecl *InterpFrame::getCallee() const {
  if (!Func)
    return nullptr;
  return Func->getDecl();
}

Pointer InterpFrame::getLocalPointer(unsigned Offset) const {
  assert(Offset < Func->getFrameSize() && "Invalid local offset.");
  return Pointer(localBlock(Offset));
}

Block *InterpFrame::getLocalBlock(unsigned Offset) const {
  return localBlock(Offset);
}

Pointer InterpFrame::getParamPointer(unsigned Index) {
  assert(!isBottomFrame());

  Block *B = argBlock(Index);

  // Copy the initial value.
  if (!B->isInitialized()) {
    unsigned ByteOffset = Func->getParamDescriptor(Index).Offset;
    assert(B->getDescriptor()->isPrimitive());
    B->invokeCtor();
    TYPE_SWITCH(B->getDescriptor()->getPrimType(),
                new (B->data()) T(stackRef<T>(ByteOffset)));
    assert(B->isInitialized());
  }

  return Pointer(B);
}

static bool funcHasUsableBody(const Function *F) {
  assert(F);

  if (F->isConstructor() || F->isDestructor())
    return true;

  return !F->getDecl()->isImplicit();
}

SourceInfo InterpFrame::getSource(CodePtr PC) const {
  if (!Func)
    return S.getSource(PC);

  // Implicitly created functions don't have any code we could point at,
  // so return the call site.
  if (Func && !funcHasUsableBody(Func) && Caller)
    return Caller->getSource(getRetOpPC());

  // Similarly, if the resulting source location is invalid anyway,
  // point to the caller instead.
  SourceInfo Result = Func->getSource(PC);
  if (Result.getLoc().isInvalid() && Caller)
    return Caller->getSource(getRetOpPC());

  return Result;
}

bool InterpFrame::isStdFunction() const {
  if (!Func)
    return false;
  for (const DeclContext *DC = Func->getDecl(); DC; DC = DC->getParent())
    if (DC->isStdNamespace())
      return true;

  return false;
}
