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