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