diff options
Diffstat (limited to 'clang/lib/AST/Interp/InterpState.cpp')
| -rw-r--r-- | clang/lib/AST/Interp/InterpState.cpp | 74 | 
1 files changed, 74 insertions, 0 deletions
| diff --git a/clang/lib/AST/Interp/InterpState.cpp b/clang/lib/AST/Interp/InterpState.cpp new file mode 100644 index 000000000000..25684f3c0939 --- /dev/null +++ b/clang/lib/AST/Interp/InterpState.cpp @@ -0,0 +1,74 @@ +//===--- 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 <limits> +#include "Function.h" +#include "InterpFrame.h" +#include "InterpStack.h" +#include "Opcode.h" +#include "PrimType.h" +#include "Program.h" +#include "State.h" + +using namespace clang; +using namespace clang::interp; + +using APSInt = llvm::APSInt; + +InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, +                         Context &Ctx, SourceMapper *M) +    : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr), +      CallStackDepth(Parent.getCallStackDepth() + 1) {} + +InterpState::~InterpState() { +  while (Current) { +    InterpFrame *Next = Current->Caller; +    delete Current; +    Current = Next; +  } + +  while (DeadBlocks) { +    DeadBlock *Next = DeadBlocks->Next; +    free(DeadBlocks); +    DeadBlocks = Next; +  } +} + +Frame *InterpState::getCurrentFrame() { +  if (Current && Current->Caller) { +    return Current; +  } else { +    return Parent.getCurrentFrame(); +  } +} + +bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) { +  QualType Type = E->getType(); +  CCEDiag(E, diag::note_constexpr_overflow) << Value << Type; +  return noteUndefinedBehavior(); +} + +void InterpState::deallocate(Block *B) { +  Descriptor *Desc = B->getDescriptor(); +  if (B->hasPointers()) { +    size_t Size = B->getSize(); + +    // Allocate a new block, transferring over pointers. +    char *Memory = reinterpret_cast<char *>(malloc(sizeof(DeadBlock) + Size)); +    auto *D = new (Memory) DeadBlock(DeadBlocks, B); + +    // Move data from one block to another. +    if (Desc->MoveFn) +      Desc->MoveFn(B, B->data(), D->data(), Desc); +  } else { +    // Free storage, if necessary. +    if (Desc->DtorFn) +      Desc->DtorFn(B, B->data(), Desc); +  } +} | 
