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