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) 2006c3fb27SDimitry 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; 3106c3fb27SDimitry Andric std::free(DeadBlocks); 32a7dea167SDimitry Andric DeadBlocks = Next; 33a7dea167SDimitry Andric } 34a7dea167SDimitry Andric } 35a7dea167SDimitry Andric 36a7dea167SDimitry Andric Frame *InterpState::getCurrentFrame() { 3706c3fb27SDimitry 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) { 4906c3fb27SDimitry Andric assert(B); 5006c3fb27SDimitry Andric const Descriptor *Desc = B->getDescriptor(); 5106c3fb27SDimitry Andric assert(Desc); 5206c3fb27SDimitry Andric 53a7dea167SDimitry Andric if (B->hasPointers()) { 54a7dea167SDimitry Andric size_t Size = B->getSize(); 55a7dea167SDimitry Andric 56a7dea167SDimitry Andric // Allocate a new block, transferring over pointers. 5706c3fb27SDimitry Andric char *Memory = 5806c3fb27SDimitry Andric reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size)); 59a7dea167SDimitry Andric auto *D = new (Memory) DeadBlock(DeadBlocks, B); 60a7dea167SDimitry Andric 61*5f757f3fSDimitry Andric // Move data and metadata from the old block to the new (dead)block. 62*5f757f3fSDimitry Andric if (Desc->MoveFn) { 63a7dea167SDimitry Andric Desc->MoveFn(B, B->data(), D->data(), Desc); 64*5f757f3fSDimitry Andric if (Desc->getMetadataSize() > 0) 65*5f757f3fSDimitry Andric std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize()); 66*5f757f3fSDimitry Andric } 67*5f757f3fSDimitry Andric 68*5f757f3fSDimitry Andric // We moved the contents over to the DeadBlock. 69*5f757f3fSDimitry Andric B->IsInitialized = false; 70a7dea167SDimitry Andric } else { 71*5f757f3fSDimitry Andric B->invokeDtor(); 72a7dea167SDimitry Andric } 73a7dea167SDimitry Andric } 74