1 //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "InterpStack.h" 10 11 using namespace clang; 12 using namespace clang::interp; 13 14 InterpStack::~InterpStack() { 15 clear(); 16 } 17 18 void InterpStack::clear() { 19 if (Chunk && Chunk->Next) 20 free(Chunk->Next); 21 if (Chunk) 22 free(Chunk); 23 Chunk = nullptr; 24 StackSize = 0; 25 } 26 27 void *InterpStack::grow(size_t Size) { 28 assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 29 30 if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 31 if (Chunk && Chunk->Next) { 32 Chunk = Chunk->Next; 33 } else { 34 StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk); 35 if (Chunk) 36 Chunk->Next = Next; 37 Chunk = Next; 38 } 39 } 40 41 auto *Object = reinterpret_cast<void *>(Chunk->End); 42 Chunk->End += Size; 43 StackSize += Size; 44 return Object; 45 } 46 47 void *InterpStack::peek(size_t Size) { 48 assert(Chunk && "Stack is empty!"); 49 50 StackChunk *Ptr = Chunk; 51 while (Size > Ptr->size()) { 52 Size -= Ptr->size(); 53 Ptr = Ptr->Prev; 54 assert(Ptr && "Offset too large"); 55 } 56 57 return reinterpret_cast<void *>(Ptr->End - Size); 58 } 59 60 void InterpStack::shrink(size_t Size) { 61 assert(Chunk && "Chunk is empty!"); 62 63 while (Size > Chunk->size()) { 64 Size -= Chunk->size(); 65 if (Chunk->Next) { 66 free(Chunk->Next); 67 Chunk->Next = nullptr; 68 } 69 Chunk->End = Chunk->start(); 70 Chunk = Chunk->Prev; 71 assert(Chunk && "Offset too large"); 72 } 73 74 Chunk->End -= Size; 75 StackSize -= Size; 76 } 77