xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/Interp/InterpState.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
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