1950b70dcSNandor Licker //===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===//
2950b70dcSNandor Licker //
3950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information.
5950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6950b70dcSNandor Licker //
7950b70dcSNandor Licker //===----------------------------------------------------------------------===//
8950b70dcSNandor Licker 
9950b70dcSNandor Licker #include <cassert>
10*10793e79SNandor Licker #include <cstdlib>
11950b70dcSNandor Licker #include "InterpStack.h"
12950b70dcSNandor Licker 
13950b70dcSNandor Licker using namespace clang;
14950b70dcSNandor Licker using namespace clang::interp;
15950b70dcSNandor Licker 
~InterpStack()16950b70dcSNandor Licker InterpStack::~InterpStack() {
17950b70dcSNandor Licker   clear();
18950b70dcSNandor Licker }
19950b70dcSNandor Licker 
clear()20950b70dcSNandor Licker void InterpStack::clear() {
21950b70dcSNandor Licker   if (Chunk && Chunk->Next)
22950b70dcSNandor Licker     free(Chunk->Next);
23950b70dcSNandor Licker   if (Chunk)
24950b70dcSNandor Licker     free(Chunk);
25950b70dcSNandor Licker   Chunk = nullptr;
26950b70dcSNandor Licker   StackSize = 0;
27950b70dcSNandor Licker }
28950b70dcSNandor Licker 
grow(size_t Size)29950b70dcSNandor Licker void *InterpStack::grow(size_t Size) {
30950b70dcSNandor Licker   assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
31950b70dcSNandor Licker 
32950b70dcSNandor Licker   if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
33950b70dcSNandor Licker     if (Chunk && Chunk->Next) {
34950b70dcSNandor Licker       Chunk = Chunk->Next;
35950b70dcSNandor Licker     } else {
36950b70dcSNandor Licker       StackChunk *Next = new (malloc(ChunkSize)) StackChunk(Chunk);
37950b70dcSNandor Licker       if (Chunk)
38950b70dcSNandor Licker         Chunk->Next = Next;
39950b70dcSNandor Licker       Chunk = Next;
40950b70dcSNandor Licker     }
41950b70dcSNandor Licker   }
42950b70dcSNandor Licker 
43950b70dcSNandor Licker   auto *Object = reinterpret_cast<void *>(Chunk->End);
44950b70dcSNandor Licker   Chunk->End += Size;
45950b70dcSNandor Licker   StackSize += Size;
46950b70dcSNandor Licker   return Object;
47950b70dcSNandor Licker }
48950b70dcSNandor Licker 
peek(size_t Size)49950b70dcSNandor Licker void *InterpStack::peek(size_t Size) {
50950b70dcSNandor Licker   assert(Chunk && "Stack is empty!");
51950b70dcSNandor Licker 
52950b70dcSNandor Licker   StackChunk *Ptr = Chunk;
53950b70dcSNandor Licker   while (Size > Ptr->size()) {
54950b70dcSNandor Licker     Size -= Ptr->size();
55950b70dcSNandor Licker     Ptr = Ptr->Prev;
56950b70dcSNandor Licker     assert(Ptr && "Offset too large");
57950b70dcSNandor Licker   }
58950b70dcSNandor Licker 
59950b70dcSNandor Licker   return reinterpret_cast<void *>(Ptr->End - Size);
60950b70dcSNandor Licker }
61950b70dcSNandor Licker 
shrink(size_t Size)62950b70dcSNandor Licker void InterpStack::shrink(size_t Size) {
63950b70dcSNandor Licker   assert(Chunk && "Chunk is empty!");
64950b70dcSNandor Licker 
65950b70dcSNandor Licker   while (Size > Chunk->size()) {
66950b70dcSNandor Licker     Size -= Chunk->size();
67950b70dcSNandor Licker     if (Chunk->Next) {
68950b70dcSNandor Licker       free(Chunk->Next);
69950b70dcSNandor Licker       Chunk->Next = nullptr;
70950b70dcSNandor Licker     }
71950b70dcSNandor Licker     Chunk->End = Chunk->start();
72950b70dcSNandor Licker     Chunk = Chunk->Prev;
73950b70dcSNandor Licker     assert(Chunk && "Offset too large");
74950b70dcSNandor Licker   }
75950b70dcSNandor Licker 
76950b70dcSNandor Licker   Chunk->End -= Size;
77950b70dcSNandor Licker   StackSize -= Size;
78950b70dcSNandor Licker }
79