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