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