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