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 <cassert> 10 #include "InterpStack.h" 11 12 using namespace clang; 13 using namespace clang::interp; 14 15 InterpStack::~InterpStack() { 16 clear(); 17 } 18 19 void InterpStack::clear() { 20 if (Chunk && Chunk->Next) 21 free(Chunk->Next); 22 if (Chunk) 23 free(Chunk); 24 Chunk = nullptr; 25 StackSize = 0; 26 } 27 28 void *InterpStack::grow(size_t Size) { 29 assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 30 31 if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 32 if (Chunk && Chunk->Next) { 33 Chunk = Chunk->Next; 34 } else { 35 StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk); 36 if (Chunk) 37 Chunk->Next = Next; 38 Chunk = Next; 39 } 40 } 41 42 auto *Object = reinterpret_cast<void *>(Chunk->End); 43 Chunk->End += Size; 44 StackSize += Size; 45 return Object; 46 } 47 48 void *InterpStack::peek(size_t Size) { 49 assert(Chunk && "Stack is empty!"); 50 51 StackChunk *Ptr = Chunk; 52 while (Size > Ptr->size()) { 53 Size -= Ptr->size(); 54 Ptr = Ptr->Prev; 55 assert(Ptr && "Offset too large"); 56 } 57 58 return reinterpret_cast<void *>(Ptr->End - Size); 59 } 60 61 void InterpStack::shrink(size_t Size) { 62 assert(Chunk && "Chunk is empty!"); 63 64 while (Size > Chunk->size()) { 65 Size -= Chunk->size(); 66 if (Chunk->Next) { 67 free(Chunk->Next); 68 Chunk->Next = nullptr; 69 } 70 Chunk->End = Chunk->start(); 71 Chunk = Chunk->Prev; 72 assert(Chunk && "Offset too large"); 73 } 74 75 Chunk->End -= Size; 76 StackSize -= Size; 77 } 78