1950b70dcSNandor Licker //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===// 2950b70dcSNandor Licker // 3950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information. 5950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6950b70dcSNandor Licker // 7950b70dcSNandor Licker //===----------------------------------------------------------------------===// 8950b70dcSNandor Licker 9950b70dcSNandor Licker #include <cassert> 10*10793e79SNandor Licker #include <cstdlib> 11950b70dcSNandor Licker #include "InterpStack.h" 12950b70dcSNandor Licker 13950b70dcSNandor Licker using namespace clang; 14950b70dcSNandor Licker using namespace clang::interp; 15950b70dcSNandor Licker ~InterpStack()16950b70dcSNandor LickerInterpStack::~InterpStack() { 17950b70dcSNandor Licker clear(); 18950b70dcSNandor Licker } 19950b70dcSNandor Licker clear()20950b70dcSNandor Lickervoid InterpStack::clear() { 21950b70dcSNandor Licker if (Chunk && Chunk->Next) 22950b70dcSNandor Licker free(Chunk->Next); 23950b70dcSNandor Licker if (Chunk) 24950b70dcSNandor Licker free(Chunk); 25950b70dcSNandor Licker Chunk = nullptr; 26950b70dcSNandor Licker StackSize = 0; 27950b70dcSNandor Licker } 28950b70dcSNandor Licker grow(size_t Size)29950b70dcSNandor Lickervoid *InterpStack::grow(size_t Size) { 30950b70dcSNandor Licker assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 31950b70dcSNandor Licker 32950b70dcSNandor Licker if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 33950b70dcSNandor Licker if (Chunk && Chunk->Next) { 34950b70dcSNandor Licker Chunk = Chunk->Next; 35950b70dcSNandor Licker } else { 36950b70dcSNandor Licker StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk); 37950b70dcSNandor Licker if (Chunk) 38950b70dcSNandor Licker Chunk->Next = Next; 39950b70dcSNandor Licker Chunk = Next; 40950b70dcSNandor Licker } 41950b70dcSNandor Licker } 42950b70dcSNandor Licker 43950b70dcSNandor Licker auto *Object = reinterpret_cast<void *>(Chunk->End); 44950b70dcSNandor Licker Chunk->End += Size; 45950b70dcSNandor Licker StackSize += Size; 46950b70dcSNandor Licker return Object; 47950b70dcSNandor Licker } 48950b70dcSNandor Licker peek(size_t Size)49950b70dcSNandor Lickervoid *InterpStack::peek(size_t Size) { 50950b70dcSNandor Licker assert(Chunk && "Stack is empty!"); 51950b70dcSNandor Licker 52950b70dcSNandor Licker StackChunk *Ptr = Chunk; 53950b70dcSNandor Licker while (Size > Ptr->size()) { 54950b70dcSNandor Licker Size -= Ptr->size(); 55950b70dcSNandor Licker Ptr = Ptr->Prev; 56950b70dcSNandor Licker assert(Ptr && "Offset too large"); 57950b70dcSNandor Licker } 58950b70dcSNandor Licker 59950b70dcSNandor Licker return reinterpret_cast<void *>(Ptr->End - Size); 60950b70dcSNandor Licker } 61950b70dcSNandor Licker shrink(size_t Size)62950b70dcSNandor Lickervoid InterpStack::shrink(size_t Size) { 63950b70dcSNandor Licker assert(Chunk && "Chunk is empty!"); 64950b70dcSNandor Licker 65950b70dcSNandor Licker while (Size > Chunk->size()) { 66950b70dcSNandor Licker Size -= Chunk->size(); 67950b70dcSNandor Licker if (Chunk->Next) { 68950b70dcSNandor Licker free(Chunk->Next); 69950b70dcSNandor Licker Chunk->Next = nullptr; 70950b70dcSNandor Licker } 71950b70dcSNandor Licker Chunk->End = Chunk->start(); 72950b70dcSNandor Licker Chunk = Chunk->Prev; 73950b70dcSNandor Licker assert(Chunk && "Offset too large"); 74950b70dcSNandor Licker } 75950b70dcSNandor Licker 76950b70dcSNandor Licker Chunk->End -= Size; 77950b70dcSNandor Licker StackSize -= Size; 78950b70dcSNandor Licker } 79