InterpStack.cpp 1.8 KB

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