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 
11 using namespace clang;
12 using namespace clang::interp;
13 
14 InterpStack::~InterpStack() {
15   clear();
16 }
17 
18 void InterpStack::clear() {
19   if (Chunk && Chunk->Next)
20     free(Chunk->Next);
21   if (Chunk)
22     free(Chunk);
23   Chunk = nullptr;
24   StackSize = 0;
25 }
26 
27 void *InterpStack::grow(size_t Size) {
28   assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
29 
30   if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
31     if (Chunk && Chunk->Next) {
32       Chunk = Chunk->Next;
33     } else {
34       StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk);
35       if (Chunk)
36         Chunk->Next = Next;
37       Chunk = Next;
38     }
39   }
40 
41   auto *Object = reinterpret_cast<void *>(Chunk->End);
42   Chunk->End += Size;
43   StackSize += Size;
44   return Object;
45 }
46 
47 void *InterpStack::peek(size_t Size) {
48   assert(Chunk && "Stack is empty!");
49 
50   StackChunk *Ptr = Chunk;
51   while (Size > Ptr->size()) {
52     Size -= Ptr->size();
53     Ptr = Ptr->Prev;
54     assert(Ptr && "Offset too large");
55   }
56 
57   return reinterpret_cast<void *>(Ptr->End - Size);
58 }
59 
60 void InterpStack::shrink(size_t Size) {
61   assert(Chunk && "Chunk is empty!");
62 
63   while (Size > Chunk->size()) {
64     Size -= Chunk->size();
65     if (Chunk->Next) {
66       free(Chunk->Next);
67       Chunk->Next = nullptr;
68     }
69     Chunk->End = Chunk->start();
70     Chunk = Chunk->Prev;
71     assert(Chunk && "Offset too large");
72   }
73 
74   Chunk->End -= Size;
75   StackSize -= Size;
76 }
77