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