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