//===--- InterpState.cpp - Interpreter for the constexpr 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 "InterpState.h"
#include "InterpFrame.h"
#include "InterpStack.h"
#include "Program.h"
#include "State.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"

using namespace clang;
using namespace clang::interp;

InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
                         Context &Ctx, SourceMapper *M)
    : State(Ctx.getASTContext(), Parent.getEvalStatus()), M(M), P(P), Stk(Stk),
      Ctx(Ctx), BottomFrame(*this), Current(&BottomFrame),
      StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
  InConstantContext = Parent.InConstantContext;
  CheckingPotentialConstantExpression =
      Parent.CheckingPotentialConstantExpression;
  CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
  EvalMode = Parent.EvalMode;
}

InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
                         Context &Ctx, const Function *Func)
    : State(Ctx.getASTContext(), Parent.getEvalStatus()), M(nullptr), P(P),
      Stk(Stk), Ctx(Ctx), BottomFrame(*this), Current(&BottomFrame),
      StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
  InConstantContext = Parent.InConstantContext;
  CheckingPotentialConstantExpression =
      Parent.CheckingPotentialConstantExpression;
  CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
  EvalMode = Parent.EvalMode;
}

bool InterpState::inConstantContext() const {
  if (ConstantContextOverride)
    return *ConstantContextOverride;

  return InConstantContext;
}

InterpState::~InterpState() {
  while (Current && !Current->isBottomFrame()) {
    InterpFrame *Next = Current->Caller;
    delete Current;
    Current = Next;
  }
  BottomFrame.destroyScopes();

  while (DeadBlocks) {
    DeadBlock *Next = DeadBlocks->Next;

    // There might be a pointer in a global structure pointing to the dead
    // block.
    for (Pointer *P = DeadBlocks->B.Pointers; P; P = P->asBlockPointer().Next)
      DeadBlocks->B.removePointer(P);

    std::free(DeadBlocks);
    DeadBlocks = Next;
  }
}

void InterpState::cleanup() {
  // As a last resort, make sure all pointers still pointing to a dead block
  // don't point to it anymore.
  if (Alloc)
    Alloc->cleanup();
}

const Frame *InterpState::getCurrentFrame() { return Current; }

void InterpState::deallocate(Block *B) {
  assert(B);
  assert(!B->isDynamic());
  assert(!B->isStatic());
  assert(!B->isDead());

  // The block might have a pointer saved in a field in its data
  // that points to the block itself. We call the dtor first,
  // which will destroy all the data but leave InlineDescriptors
  // intact. If the block THEN still has pointers, we create a
  // DeadBlock for it.
  if (B->IsInitialized)
    B->invokeDtor();

  assert(!B->isInitialized());
  if (B->hasPointers()) {
    size_t Size = B->getSize();
    // Allocate a new block, transferring over pointers.
    char *Memory =
        reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size));
    auto *D = new (Memory) DeadBlock(DeadBlocks, B);
    // Since the block doesn't hold any actual data anymore, we can just
    // memcpy() everything over.
    std::memcpy(D->rawData(), B->rawData(), Size);
    D->B.IsInitialized = false;
  }
}

bool InterpState::maybeDiagnoseDanglingAllocations() {
  if (!Alloc)
    return true;

  bool NoAllocationsLeft = !Alloc->hasAllocations();

  if (!checkingPotentialConstantExpression()) {
    for (const auto &[Source, Site] : Alloc->allocation_sites()) {
      assert(!Site.empty());

      CCEDiag(Source->getExprLoc(), diag::note_constexpr_memory_leak)
          << (Site.size() - 1) << Source->getSourceRange();
    }
  }
  // Keep evaluating before C++20, since the CXXNewExpr wasn't valid there
  // in the first place.
  return NoAllocationsLeft || !getLangOpts().CPlusPlus20;
}

StdAllocatorCaller InterpState::getStdAllocatorCaller(StringRef Name) const {
  for (const InterpFrame *F = Current; F; F = F->Caller) {
    const Function *Func = F->getFunction();
    if (!Func)
      continue;
    const auto *MD = dyn_cast_if_present<CXXMethodDecl>(Func->getDecl());
    if (!MD)
      continue;
    const IdentifierInfo *FnII = MD->getIdentifier();
    if (!FnII || !FnII->isStr(Name))
      continue;

    const auto *CTSD =
        dyn_cast<ClassTemplateSpecializationDecl>(MD->getParent());
    if (!CTSD)
      continue;

    const IdentifierInfo *ClassII = CTSD->getIdentifier();
    const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
    if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") &&
        TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) {
      QualType ElemType = TAL[0].getAsType();
      const auto *NewCall = cast<CallExpr>(F->Caller->getExpr(F->getRetPC()));
      return {NewCall, ElemType};
    }
  }

  return {};
}

bool InterpState::noteStep(CodePtr OpPC) {
  if (InfiniteSteps)
    return true;

  --StepsLeft;
  if (StepsLeft != 0)
    return true;

  FFDiag(Current->getSource(OpPC), diag::note_constexpr_step_limit_exceeded);
  return false;
}
