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