//===--- 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 "Floating.h"
#include "Function.h"
#include "InterpStack.h"
#include "InterpState.h"
#include "Pointer.h"
#include "PrimType.h"
#include "Program.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"

using namespace clang;
using namespace clang::interp;

InterpFrame::InterpFrame(InterpState &S, const Function *Func,
                         InterpFrame *Caller, CodePtr RetPC)
    : Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func),
      RetPC(RetPC), ArgSize(Func ? Func->getArgSize() : 0),
      Args(static_cast<char *>(S.Stk.top())), FrameOffset(S.Stk.size()) {
  if (!Func)
    return;

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

  Locals = std::make_unique<char[]>(FrameSize);
  for (auto &Scope : Func->scopes()) {
    for (auto &Local : Scope.locals()) {
      Block *B = new (localBlock(Local.Offset)) Block(Local.Desc);
      B->invokeCtor();
      InlineDescriptor *ID = localInlineDesc(Local.Offset);
      ID->Desc = Local.Desc;
      ID->IsActive = true;
      ID->Offset = sizeof(InlineDescriptor);
      ID->IsBase = false;
      ID->IsFieldMutable = false;
      ID->IsConst = false;
      ID->IsInitialized = false;
    }
  }
}

InterpFrame::InterpFrame(InterpState &S, const Function *Func, CodePtr RetPC)
    : InterpFrame(S, Func, S.Current, RetPC) {
  // 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()).
  if (Func->hasRVO())
    RVOPtr = stackRef<Pointer>(0);

  if (Func->hasThisPointer()) {
    if (Func->hasRVO())
      This = stackRef<Pointer>(sizeof(Pointer));
    else
      This = stackRef<Pointer>(0);
  }
}

InterpFrame::~InterpFrame() {
  for (auto &Param : Params)
    S.deallocate(reinterpret_cast<Block *>(Param.second.get()));

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

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

void InterpFrame::popArgs() {
  for (PrimType Ty : Func->args_reverse())
    TYPE_SWITCH(Ty, S.Stk.discard<T>());
}

template <typename T>
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType) {
  OS << V;
}

template <>
void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx,
           QualType Ty) {
  if (P.isZero()) {
    OS << "nullptr";
    return;
  }

  auto printDesc = [&OS, &Ctx](const Descriptor *Desc) {
    if (const auto *D = Desc->asDecl()) {
      // Subfields or named values.
      if (const auto *VD = dyn_cast<ValueDecl>(D)) {
        OS << *VD;
        return;
      }
      // Base classes.
      if (isa<RecordDecl>(D))
        return;
    }
    // Temporary expression.
    if (const auto *E = Desc->asExpr()) {
      E->printPretty(OS, nullptr, Ctx.getPrintingPolicy());
      return;
    }
    llvm_unreachable("Invalid descriptor type");
  };

  if (!Ty->isReferenceType())
    OS << "&";
  llvm::SmallVector<Pointer, 2> Levels;
  for (Pointer F = P; !F.isRoot(); ) {
    Levels.push_back(F);
    F = F.isArrayElement() ? F.getArray().expand() : F.getBase();
  }

  // Drop the first pointer since we print it unconditionally anyway.
  if (!Levels.empty())
    Levels.erase(Levels.begin());

  printDesc(P.getDeclDesc());
  for (const auto &It : Levels) {
    if (It.inArray()) {
      OS << "[" << It.expand().getIndex() << "]";
      continue;
    }
    if (auto Index = It.getIndex()) {
      OS << " + " << Index;
      continue;
    }
    OS << ".";
    printDesc(It.getFieldDesc());
  }
}

void InterpFrame::describe(llvm::raw_ostream &OS) const {
  const FunctionDecl *F = getCallee();
  if (const auto *M = dyn_cast<CXXMethodDecl>(F);
      M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
    print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
    OS << "->";
  }
  OS << *F << "(";
  unsigned Off = 0;

  Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;
  Off += Func->hasThisPointer() ? primSize(PT_Ptr) : 0;

  for (unsigned I = 0, N = F->getNumParams(); I < N; ++I) {
    QualType Ty = F->getParamDecl(I)->getType();

    PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr);

    TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty));
    Off += align(primSize(PrimTy));
    if (I + 1 != N)
      OS << ", ";
  }
  OS << ")";
}

Frame *InterpFrame::getCaller() const {
  if (Caller->Caller)
    return Caller;
  return S.getSplitFrame();
}

SourceRange InterpFrame::getCallRange() const {
  if (!Caller->Func)
    return S.getRange(nullptr, {});
  return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t));
}

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

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

Pointer InterpFrame::getParamPointer(unsigned Off) {
  // Return the block if it was created previously.
  auto Pt = Params.find(Off);
  if (Pt != Params.end()) {
    return Pointer(reinterpret_cast<Block *>(Pt->second.get()));
  }

  // Allocate memory to store the parameter and the block metadata.
  const auto &Desc = Func->getParamDescriptor(Off);
  size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize();
  auto Memory = std::make_unique<char[]>(BlockSize);
  auto *B = new (Memory.get()) Block(Desc.second);

  // Copy the initial value.
  TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off)));

  // Record the param.
  Params.insert({Off, std::move(Memory)});
  return Pointer(B);
}

SourceInfo InterpFrame::getSource(CodePtr PC) const {
  // Implicitly created functions don't have any code we could point at,
  // so return the call site.
  if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller)
    return Caller->getSource(RetPC);

  return S.getSource(Func, PC);
}

const Expr *InterpFrame::getExpr(CodePtr PC) const {
  return S.getExpr(Func, PC);
}

SourceLocation InterpFrame::getLocation(CodePtr PC) const {
  return S.getLocation(Func, PC);
}

SourceRange InterpFrame::getRange(CodePtr PC) const {
  if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller)
    return Caller->getRange(RetPC);

  return S.getRange(Func, PC);
}
