1a07aba5dSTimm Baeder //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder 9a07aba5dSTimm Baeder #include "InterpStack.h" 10a07aba5dSTimm Baeder #include "Boolean.h" 11*048bc672STimm Baeder #include "FixedPoint.h" 12a07aba5dSTimm Baeder #include "Floating.h" 13a07aba5dSTimm Baeder #include "Integral.h" 14a07aba5dSTimm Baeder #include "MemberPointer.h" 15a07aba5dSTimm Baeder #include "Pointer.h" 16a07aba5dSTimm Baeder #include <cassert> 17a07aba5dSTimm Baeder #include <cstdlib> 18a07aba5dSTimm Baeder 19a07aba5dSTimm Baeder using namespace clang; 20a07aba5dSTimm Baeder using namespace clang::interp; 21a07aba5dSTimm Baeder 22a07aba5dSTimm Baeder InterpStack::~InterpStack() { clear(); } 23a07aba5dSTimm Baeder 24a07aba5dSTimm Baeder void InterpStack::clear() { 25a07aba5dSTimm Baeder if (Chunk && Chunk->Next) 26a07aba5dSTimm Baeder std::free(Chunk->Next); 27a07aba5dSTimm Baeder if (Chunk) 28a07aba5dSTimm Baeder std::free(Chunk); 29a07aba5dSTimm Baeder Chunk = nullptr; 30a07aba5dSTimm Baeder StackSize = 0; 31a07aba5dSTimm Baeder #ifndef NDEBUG 32a07aba5dSTimm Baeder ItemTypes.clear(); 33a07aba5dSTimm Baeder #endif 34a07aba5dSTimm Baeder } 35a07aba5dSTimm Baeder 36eef8116bSTimm Baeder void InterpStack::clearTo(size_t NewSize) { 37eef8116bSTimm Baeder assert(NewSize <= size()); 38eef8116bSTimm Baeder size_t ToShrink = size() - NewSize; 39eef8116bSTimm Baeder if (ToShrink == 0) 40eef8116bSTimm Baeder return; 41eef8116bSTimm Baeder 42eef8116bSTimm Baeder shrink(ToShrink); 43eef8116bSTimm Baeder assert(size() == NewSize); 44eef8116bSTimm Baeder } 45eef8116bSTimm Baeder 46a07aba5dSTimm Baeder void *InterpStack::grow(size_t Size) { 47a07aba5dSTimm Baeder assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 48a07aba5dSTimm Baeder 49a07aba5dSTimm Baeder if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 50a07aba5dSTimm Baeder if (Chunk && Chunk->Next) { 51a07aba5dSTimm Baeder Chunk = Chunk->Next; 52a07aba5dSTimm Baeder } else { 53a07aba5dSTimm Baeder StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk); 54a07aba5dSTimm Baeder if (Chunk) 55a07aba5dSTimm Baeder Chunk->Next = Next; 56a07aba5dSTimm Baeder Chunk = Next; 57a07aba5dSTimm Baeder } 58a07aba5dSTimm Baeder } 59a07aba5dSTimm Baeder 60a07aba5dSTimm Baeder auto *Object = reinterpret_cast<void *>(Chunk->End); 61a07aba5dSTimm Baeder Chunk->End += Size; 62a07aba5dSTimm Baeder StackSize += Size; 63a07aba5dSTimm Baeder return Object; 64a07aba5dSTimm Baeder } 65a07aba5dSTimm Baeder 66a07aba5dSTimm Baeder void *InterpStack::peekData(size_t Size) const { 67a07aba5dSTimm Baeder assert(Chunk && "Stack is empty!"); 68a07aba5dSTimm Baeder 69a07aba5dSTimm Baeder StackChunk *Ptr = Chunk; 70a07aba5dSTimm Baeder while (Size > Ptr->size()) { 71a07aba5dSTimm Baeder Size -= Ptr->size(); 72a07aba5dSTimm Baeder Ptr = Ptr->Prev; 73a07aba5dSTimm Baeder assert(Ptr && "Offset too large"); 74a07aba5dSTimm Baeder } 75a07aba5dSTimm Baeder 76a07aba5dSTimm Baeder return reinterpret_cast<void *>(Ptr->End - Size); 77a07aba5dSTimm Baeder } 78a07aba5dSTimm Baeder 79a07aba5dSTimm Baeder void InterpStack::shrink(size_t Size) { 80a07aba5dSTimm Baeder assert(Chunk && "Chunk is empty!"); 81a07aba5dSTimm Baeder 82a07aba5dSTimm Baeder while (Size > Chunk->size()) { 83a07aba5dSTimm Baeder Size -= Chunk->size(); 84a07aba5dSTimm Baeder if (Chunk->Next) { 85a07aba5dSTimm Baeder std::free(Chunk->Next); 86a07aba5dSTimm Baeder Chunk->Next = nullptr; 87a07aba5dSTimm Baeder } 88a07aba5dSTimm Baeder Chunk->End = Chunk->start(); 89a07aba5dSTimm Baeder Chunk = Chunk->Prev; 90a07aba5dSTimm Baeder assert(Chunk && "Offset too large"); 91a07aba5dSTimm Baeder } 92a07aba5dSTimm Baeder 93a07aba5dSTimm Baeder Chunk->End -= Size; 94a07aba5dSTimm Baeder StackSize -= Size; 95eef8116bSTimm Baeder 96eef8116bSTimm Baeder #ifndef NDEBUG 97eef8116bSTimm Baeder size_t TypesSize = 0; 98eef8116bSTimm Baeder for (PrimType T : ItemTypes) 99eef8116bSTimm Baeder TYPE_SWITCH(T, { TypesSize += aligned_size<T>(); }); 100eef8116bSTimm Baeder 101eef8116bSTimm Baeder size_t StackSize = size(); 102eef8116bSTimm Baeder while (TypesSize > StackSize) { 103eef8116bSTimm Baeder TYPE_SWITCH(ItemTypes.back(), { 104eef8116bSTimm Baeder TypesSize -= aligned_size<T>(); 105eef8116bSTimm Baeder ItemTypes.pop_back(); 106eef8116bSTimm Baeder }); 107eef8116bSTimm Baeder } 108eef8116bSTimm Baeder assert(TypesSize == StackSize); 109eef8116bSTimm Baeder #endif 110a07aba5dSTimm Baeder } 111a07aba5dSTimm Baeder 112a07aba5dSTimm Baeder void InterpStack::dump() const { 113a07aba5dSTimm Baeder #ifndef NDEBUG 114a07aba5dSTimm Baeder llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n'; 115a07aba5dSTimm Baeder if (ItemTypes.empty()) 116a07aba5dSTimm Baeder return; 117a07aba5dSTimm Baeder 118a07aba5dSTimm Baeder size_t Index = 0; 119a07aba5dSTimm Baeder size_t Offset = 0; 120a07aba5dSTimm Baeder 121a07aba5dSTimm Baeder // The type of the item on the top of the stack is inserted to the back 122a07aba5dSTimm Baeder // of the vector, so the iteration has to happen backwards. 123a07aba5dSTimm Baeder for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) { 124a07aba5dSTimm Baeder Offset += align(primSize(*TyIt)); 125a07aba5dSTimm Baeder 126a07aba5dSTimm Baeder llvm::errs() << Index << '/' << Offset << ": "; 127a07aba5dSTimm Baeder TYPE_SWITCH(*TyIt, { 128a07aba5dSTimm Baeder const T &V = peek<T>(Offset); 129a07aba5dSTimm Baeder llvm::errs() << V; 130a07aba5dSTimm Baeder }); 131a07aba5dSTimm Baeder llvm::errs() << '\n'; 132a07aba5dSTimm Baeder 133a07aba5dSTimm Baeder ++Index; 134a07aba5dSTimm Baeder } 135a07aba5dSTimm Baeder #endif 136a07aba5dSTimm Baeder } 137