xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/Interp/InterpStack.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1*7330f729Sjoerg //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===//
2*7330f729Sjoerg //
3*7330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*7330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7330f729Sjoerg //
7*7330f729Sjoerg //===----------------------------------------------------------------------===//
8*7330f729Sjoerg 
9*7330f729Sjoerg #include <cassert>
10*7330f729Sjoerg #include <cstdlib>
11*7330f729Sjoerg #include "InterpStack.h"
12*7330f729Sjoerg 
13*7330f729Sjoerg using namespace clang;
14*7330f729Sjoerg using namespace clang::interp;
15*7330f729Sjoerg 
~InterpStack()16*7330f729Sjoerg InterpStack::~InterpStack() {
17*7330f729Sjoerg   clear();
18*7330f729Sjoerg }
19*7330f729Sjoerg 
clear()20*7330f729Sjoerg void InterpStack::clear() {
21*7330f729Sjoerg   if (Chunk && Chunk->Next)
22*7330f729Sjoerg     free(Chunk->Next);
23*7330f729Sjoerg   if (Chunk)
24*7330f729Sjoerg     free(Chunk);
25*7330f729Sjoerg   Chunk = nullptr;
26*7330f729Sjoerg   StackSize = 0;
27*7330f729Sjoerg }
28*7330f729Sjoerg 
grow(size_t Size)29*7330f729Sjoerg void *InterpStack::grow(size_t Size) {
30*7330f729Sjoerg   assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
31*7330f729Sjoerg 
32*7330f729Sjoerg   if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
33*7330f729Sjoerg     if (Chunk && Chunk->Next) {
34*7330f729Sjoerg       Chunk = Chunk->Next;
35*7330f729Sjoerg     } else {
36*7330f729Sjoerg       StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk);
37*7330f729Sjoerg       if (Chunk)
38*7330f729Sjoerg         Chunk->Next = Next;
39*7330f729Sjoerg       Chunk = Next;
40*7330f729Sjoerg     }
41*7330f729Sjoerg   }
42*7330f729Sjoerg 
43*7330f729Sjoerg   auto *Object = reinterpret_cast<void *>(Chunk->End);
44*7330f729Sjoerg   Chunk->End += Size;
45*7330f729Sjoerg   StackSize += Size;
46*7330f729Sjoerg   return Object;
47*7330f729Sjoerg }
48*7330f729Sjoerg 
peek(size_t Size)49*7330f729Sjoerg void *InterpStack::peek(size_t Size) {
50*7330f729Sjoerg   assert(Chunk && "Stack is empty!");
51*7330f729Sjoerg 
52*7330f729Sjoerg   StackChunk *Ptr = Chunk;
53*7330f729Sjoerg   while (Size > Ptr->size()) {
54*7330f729Sjoerg     Size -= Ptr->size();
55*7330f729Sjoerg     Ptr = Ptr->Prev;
56*7330f729Sjoerg     assert(Ptr && "Offset too large");
57*7330f729Sjoerg   }
58*7330f729Sjoerg 
59*7330f729Sjoerg   return reinterpret_cast<void *>(Ptr->End - Size);
60*7330f729Sjoerg }
61*7330f729Sjoerg 
shrink(size_t Size)62*7330f729Sjoerg void InterpStack::shrink(size_t Size) {
63*7330f729Sjoerg   assert(Chunk && "Chunk is empty!");
64*7330f729Sjoerg 
65*7330f729Sjoerg   while (Size > Chunk->size()) {
66*7330f729Sjoerg     Size -= Chunk->size();
67*7330f729Sjoerg     if (Chunk->Next) {
68*7330f729Sjoerg       free(Chunk->Next);
69*7330f729Sjoerg       Chunk->Next = nullptr;
70*7330f729Sjoerg     }
71*7330f729Sjoerg     Chunk->End = Chunk->start();
72*7330f729Sjoerg     Chunk = Chunk->Prev;
73*7330f729Sjoerg     assert(Chunk && "Offset too large");
74*7330f729Sjoerg   }
75*7330f729Sjoerg 
76*7330f729Sjoerg   Chunk->End -= Size;
77*7330f729Sjoerg   StackSize -= Size;
78*7330f729Sjoerg }
79