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