InterpStack.cpp revision 358851
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
13using namespace clang;
14using namespace clang::interp;
15
16InterpStack::~InterpStack() {
17  clear();
18}
19
20void 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
29void *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
49void *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
62void 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