1a7dea167SDimitry Andric //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 906c3fb27SDimitry Andric #include "InterpStack.h" 1006c3fb27SDimitry Andric #include "Boolean.h" 1106c3fb27SDimitry Andric #include "Floating.h" 1206c3fb27SDimitry Andric #include "Integral.h" 13*5f757f3fSDimitry Andric #include "Pointer.h" 14a7dea167SDimitry Andric #include <cassert> 15a7dea167SDimitry Andric #include <cstdlib> 16a7dea167SDimitry Andric 17a7dea167SDimitry Andric using namespace clang; 18a7dea167SDimitry Andric using namespace clang::interp; 19a7dea167SDimitry Andric 20a7dea167SDimitry Andric InterpStack::~InterpStack() { 21a7dea167SDimitry Andric clear(); 22a7dea167SDimitry Andric } 23a7dea167SDimitry Andric 24a7dea167SDimitry Andric void InterpStack::clear() { 25a7dea167SDimitry Andric if (Chunk && Chunk->Next) 2606c3fb27SDimitry Andric std::free(Chunk->Next); 27a7dea167SDimitry Andric if (Chunk) 2806c3fb27SDimitry Andric std::free(Chunk); 29a7dea167SDimitry Andric Chunk = nullptr; 30a7dea167SDimitry Andric StackSize = 0; 3106c3fb27SDimitry Andric #ifndef NDEBUG 3206c3fb27SDimitry Andric ItemTypes.clear(); 3306c3fb27SDimitry Andric #endif 34a7dea167SDimitry Andric } 35a7dea167SDimitry Andric 36a7dea167SDimitry Andric void *InterpStack::grow(size_t Size) { 37a7dea167SDimitry Andric assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 38a7dea167SDimitry Andric 39a7dea167SDimitry Andric if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 40a7dea167SDimitry Andric if (Chunk && Chunk->Next) { 41a7dea167SDimitry Andric Chunk = Chunk->Next; 42a7dea167SDimitry Andric } else { 4306c3fb27SDimitry Andric StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk); 44a7dea167SDimitry Andric if (Chunk) 45a7dea167SDimitry Andric Chunk->Next = Next; 46a7dea167SDimitry Andric Chunk = Next; 47a7dea167SDimitry Andric } 48a7dea167SDimitry Andric } 49a7dea167SDimitry Andric 50a7dea167SDimitry Andric auto *Object = reinterpret_cast<void *>(Chunk->End); 51a7dea167SDimitry Andric Chunk->End += Size; 52a7dea167SDimitry Andric StackSize += Size; 53a7dea167SDimitry Andric return Object; 54a7dea167SDimitry Andric } 55a7dea167SDimitry Andric 5606c3fb27SDimitry Andric void *InterpStack::peekData(size_t Size) const { 57a7dea167SDimitry Andric assert(Chunk && "Stack is empty!"); 58a7dea167SDimitry Andric 59a7dea167SDimitry Andric StackChunk *Ptr = Chunk; 60a7dea167SDimitry Andric while (Size > Ptr->size()) { 61a7dea167SDimitry Andric Size -= Ptr->size(); 62a7dea167SDimitry Andric Ptr = Ptr->Prev; 63a7dea167SDimitry Andric assert(Ptr && "Offset too large"); 64a7dea167SDimitry Andric } 65a7dea167SDimitry Andric 66a7dea167SDimitry Andric return reinterpret_cast<void *>(Ptr->End - Size); 67a7dea167SDimitry Andric } 68a7dea167SDimitry Andric 69a7dea167SDimitry Andric void InterpStack::shrink(size_t Size) { 70a7dea167SDimitry Andric assert(Chunk && "Chunk is empty!"); 71a7dea167SDimitry Andric 72a7dea167SDimitry Andric while (Size > Chunk->size()) { 73a7dea167SDimitry Andric Size -= Chunk->size(); 74a7dea167SDimitry Andric if (Chunk->Next) { 7506c3fb27SDimitry Andric std::free(Chunk->Next); 76a7dea167SDimitry Andric Chunk->Next = nullptr; 77a7dea167SDimitry Andric } 78a7dea167SDimitry Andric Chunk->End = Chunk->start(); 79a7dea167SDimitry Andric Chunk = Chunk->Prev; 80a7dea167SDimitry Andric assert(Chunk && "Offset too large"); 81a7dea167SDimitry Andric } 82a7dea167SDimitry Andric 83a7dea167SDimitry Andric Chunk->End -= Size; 84a7dea167SDimitry Andric StackSize -= Size; 85a7dea167SDimitry Andric } 8606c3fb27SDimitry Andric 8706c3fb27SDimitry Andric void InterpStack::dump() const { 8806c3fb27SDimitry Andric #ifndef NDEBUG 89*5f757f3fSDimitry Andric llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n'; 9006c3fb27SDimitry Andric if (ItemTypes.empty()) 9106c3fb27SDimitry Andric return; 9206c3fb27SDimitry Andric 9306c3fb27SDimitry Andric size_t Index = 0; 94*5f757f3fSDimitry Andric size_t Offset = 0; 95*5f757f3fSDimitry Andric 96*5f757f3fSDimitry Andric // The type of the item on the top of the stack is inserted to the back 97*5f757f3fSDimitry Andric // of the vector, so the iteration has to happen backwards. 98*5f757f3fSDimitry Andric for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) { 99*5f757f3fSDimitry Andric Offset += align(primSize(*TyIt)); 100*5f757f3fSDimitry Andric 101*5f757f3fSDimitry Andric llvm::errs() << Index << '/' << Offset << ": "; 102*5f757f3fSDimitry Andric TYPE_SWITCH(*TyIt, { 10306c3fb27SDimitry Andric const T &V = peek<T>(Offset); 10406c3fb27SDimitry Andric llvm::errs() << V; 10506c3fb27SDimitry Andric }); 106*5f757f3fSDimitry Andric llvm::errs() << '\n'; 107*5f757f3fSDimitry Andric 10806c3fb27SDimitry Andric ++Index; 10906c3fb27SDimitry Andric } 11006c3fb27SDimitry Andric #endif 11106c3fb27SDimitry Andric } 112