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