InterpStack.cpp 1.8 KB

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