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*0fca6ea1SDimitry Andric #include "MemberPointer.h" 145f757f3fSDimitry Andric #include "Pointer.h" 15a7dea167SDimitry Andric #include <cassert> 16a7dea167SDimitry Andric #include <cstdlib> 17a7dea167SDimitry Andric 18a7dea167SDimitry Andric using namespace clang; 19a7dea167SDimitry Andric using namespace clang::interp; 20a7dea167SDimitry Andric ~InterpStack()21a7dea167SDimitry AndricInterpStack::~InterpStack() { 22a7dea167SDimitry Andric clear(); 23a7dea167SDimitry Andric } 24a7dea167SDimitry Andric clear()25a7dea167SDimitry Andricvoid InterpStack::clear() { 26a7dea167SDimitry Andric if (Chunk && Chunk->Next) 2706c3fb27SDimitry Andric std::free(Chunk->Next); 28a7dea167SDimitry Andric if (Chunk) 2906c3fb27SDimitry Andric std::free(Chunk); 30a7dea167SDimitry Andric Chunk = nullptr; 31a7dea167SDimitry Andric StackSize = 0; 3206c3fb27SDimitry Andric #ifndef NDEBUG 3306c3fb27SDimitry Andric ItemTypes.clear(); 3406c3fb27SDimitry Andric #endif 35a7dea167SDimitry Andric } 36a7dea167SDimitry Andric grow(size_t Size)37a7dea167SDimitry Andricvoid *InterpStack::grow(size_t Size) { 38a7dea167SDimitry Andric assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large"); 39a7dea167SDimitry Andric 40a7dea167SDimitry Andric if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) { 41a7dea167SDimitry Andric if (Chunk && Chunk->Next) { 42a7dea167SDimitry Andric Chunk = Chunk->Next; 43a7dea167SDimitry Andric } else { 4406c3fb27SDimitry Andric StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk); 45a7dea167SDimitry Andric if (Chunk) 46a7dea167SDimitry Andric Chunk->Next = Next; 47a7dea167SDimitry Andric Chunk = Next; 48a7dea167SDimitry Andric } 49a7dea167SDimitry Andric } 50a7dea167SDimitry Andric 51a7dea167SDimitry Andric auto *Object = reinterpret_cast<void *>(Chunk->End); 52a7dea167SDimitry Andric Chunk->End += Size; 53a7dea167SDimitry Andric StackSize += Size; 54a7dea167SDimitry Andric return Object; 55a7dea167SDimitry Andric } 56a7dea167SDimitry Andric peekData(size_t Size) const5706c3fb27SDimitry Andricvoid *InterpStack::peekData(size_t Size) const { 58a7dea167SDimitry Andric assert(Chunk && "Stack is empty!"); 59a7dea167SDimitry Andric 60a7dea167SDimitry Andric StackChunk *Ptr = Chunk; 61a7dea167SDimitry Andric while (Size > Ptr->size()) { 62a7dea167SDimitry Andric Size -= Ptr->size(); 63a7dea167SDimitry Andric Ptr = Ptr->Prev; 64a7dea167SDimitry Andric assert(Ptr && "Offset too large"); 65a7dea167SDimitry Andric } 66a7dea167SDimitry Andric 67a7dea167SDimitry Andric return reinterpret_cast<void *>(Ptr->End - Size); 68a7dea167SDimitry Andric } 69a7dea167SDimitry Andric shrink(size_t Size)70a7dea167SDimitry Andricvoid InterpStack::shrink(size_t Size) { 71a7dea167SDimitry Andric assert(Chunk && "Chunk is empty!"); 72a7dea167SDimitry Andric 73a7dea167SDimitry Andric while (Size > Chunk->size()) { 74a7dea167SDimitry Andric Size -= Chunk->size(); 75a7dea167SDimitry Andric if (Chunk->Next) { 7606c3fb27SDimitry Andric std::free(Chunk->Next); 77a7dea167SDimitry Andric Chunk->Next = nullptr; 78a7dea167SDimitry Andric } 79a7dea167SDimitry Andric Chunk->End = Chunk->start(); 80a7dea167SDimitry Andric Chunk = Chunk->Prev; 81a7dea167SDimitry Andric assert(Chunk && "Offset too large"); 82a7dea167SDimitry Andric } 83a7dea167SDimitry Andric 84a7dea167SDimitry Andric Chunk->End -= Size; 85a7dea167SDimitry Andric StackSize -= Size; 86a7dea167SDimitry Andric } 8706c3fb27SDimitry Andric dump() const8806c3fb27SDimitry Andricvoid InterpStack::dump() const { 8906c3fb27SDimitry Andric #ifndef NDEBUG 905f757f3fSDimitry Andric llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n'; 9106c3fb27SDimitry Andric if (ItemTypes.empty()) 9206c3fb27SDimitry Andric return; 9306c3fb27SDimitry Andric 9406c3fb27SDimitry Andric size_t Index = 0; 955f757f3fSDimitry Andric size_t Offset = 0; 965f757f3fSDimitry Andric 975f757f3fSDimitry Andric // The type of the item on the top of the stack is inserted to the back 985f757f3fSDimitry Andric // of the vector, so the iteration has to happen backwards. 995f757f3fSDimitry Andric for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) { 1005f757f3fSDimitry Andric Offset += align(primSize(*TyIt)); 1015f757f3fSDimitry Andric 1025f757f3fSDimitry Andric llvm::errs() << Index << '/' << Offset << ": "; 1035f757f3fSDimitry Andric TYPE_SWITCH(*TyIt, { 10406c3fb27SDimitry Andric const T &V = peek<T>(Offset); 10506c3fb27SDimitry Andric llvm::errs() << V; 10606c3fb27SDimitry Andric }); 1075f757f3fSDimitry Andric llvm::errs() << '\n'; 1085f757f3fSDimitry Andric 10906c3fb27SDimitry Andric ++Index; 11006c3fb27SDimitry Andric } 11106c3fb27SDimitry Andric #endif 11206c3fb27SDimitry Andric } 113