1*950b70dcSNandor Licker //===--- InterpState.cpp - Interpreter for the constexpr VM -----*- C++ -*-===//
2*950b70dcSNandor Licker //
3*950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information.
5*950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*950b70dcSNandor Licker //
7*950b70dcSNandor Licker //===----------------------------------------------------------------------===//
8*950b70dcSNandor Licker
9*950b70dcSNandor Licker #include "InterpState.h"
10*950b70dcSNandor Licker #include <limits>
11*950b70dcSNandor Licker #include "Function.h"
12*950b70dcSNandor Licker #include "InterpFrame.h"
13*950b70dcSNandor Licker #include "InterpStack.h"
14*950b70dcSNandor Licker #include "Opcode.h"
15*950b70dcSNandor Licker #include "PrimType.h"
16*950b70dcSNandor Licker #include "Program.h"
17*950b70dcSNandor Licker #include "State.h"
18*950b70dcSNandor Licker
19*950b70dcSNandor Licker using namespace clang;
20*950b70dcSNandor Licker using namespace clang::interp;
21*950b70dcSNandor Licker
22*950b70dcSNandor Licker using APSInt = llvm::APSInt;
23*950b70dcSNandor Licker
InterpState(State & Parent,Program & P,InterpStack & Stk,Context & Ctx,SourceMapper * M)24*950b70dcSNandor Licker InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk,
25*950b70dcSNandor Licker Context &Ctx, SourceMapper *M)
26*950b70dcSNandor Licker : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr),
27*950b70dcSNandor Licker CallStackDepth(Parent.getCallStackDepth() + 1) {}
28*950b70dcSNandor Licker
~InterpState()29*950b70dcSNandor Licker InterpState::~InterpState() {
30*950b70dcSNandor Licker while (Current) {
31*950b70dcSNandor Licker InterpFrame *Next = Current->Caller;
32*950b70dcSNandor Licker delete Current;
33*950b70dcSNandor Licker Current = Next;
34*950b70dcSNandor Licker }
35*950b70dcSNandor Licker
36*950b70dcSNandor Licker while (DeadBlocks) {
37*950b70dcSNandor Licker DeadBlock *Next = DeadBlocks->Next;
38*950b70dcSNandor Licker free(DeadBlocks);
39*950b70dcSNandor Licker DeadBlocks = Next;
40*950b70dcSNandor Licker }
41*950b70dcSNandor Licker }
42*950b70dcSNandor Licker
getCurrentFrame()43*950b70dcSNandor Licker Frame *InterpState::getCurrentFrame() {
44*950b70dcSNandor Licker if (Current && Current->Caller) {
45*950b70dcSNandor Licker return Current;
46*950b70dcSNandor Licker } else {
47*950b70dcSNandor Licker return Parent.getCurrentFrame();
48*950b70dcSNandor Licker }
49*950b70dcSNandor Licker }
50*950b70dcSNandor Licker
reportOverflow(const Expr * E,const llvm::APSInt & Value)51*950b70dcSNandor Licker bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) {
52*950b70dcSNandor Licker QualType Type = E->getType();
53*950b70dcSNandor Licker CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
54*950b70dcSNandor Licker return noteUndefinedBehavior();
55*950b70dcSNandor Licker }
56*950b70dcSNandor Licker
deallocate(Block * B)57*950b70dcSNandor Licker void InterpState::deallocate(Block *B) {
58*950b70dcSNandor Licker Descriptor *Desc = B->getDescriptor();
59*950b70dcSNandor Licker if (B->hasPointers()) {
60*950b70dcSNandor Licker size_t Size = B->getSize();
61*950b70dcSNandor Licker
62*950b70dcSNandor Licker // Allocate a new block, transferring over pointers.
63*950b70dcSNandor Licker char *Memory = reinterpret_cast<char *>(malloc(sizeof(DeadBlock) + Size));
64*950b70dcSNandor Licker auto *D = new (Memory) DeadBlock(DeadBlocks, B);
65*950b70dcSNandor Licker
66*950b70dcSNandor Licker // Move data from one block to another.
67*950b70dcSNandor Licker if (Desc->MoveFn)
68*950b70dcSNandor Licker Desc->MoveFn(B, B->data(), D->data(), Desc);
69*950b70dcSNandor Licker } else {
70*950b70dcSNandor Licker // Free storage, if necessary.
71*950b70dcSNandor Licker if (Desc->DtorFn)
72*950b70dcSNandor Licker Desc->DtorFn(B, B->data(), Desc);
73*950b70dcSNandor Licker }
74*950b70dcSNandor Licker }
75