clang 20.0.0git
InterpStack.cpp
Go to the documentation of this file.
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 "InterpStack.h"
10#include "Boolean.h"
11#include "Floating.h"
12#include "Integral.h"
13#include "MemberPointer.h"
14#include "Pointer.h"
15#include <cassert>
16#include <cstdlib>
17
18using namespace clang;
19using namespace clang::interp;
20
22
24 if (Chunk && Chunk->Next)
25 std::free(Chunk->Next);
26 if (Chunk)
27 std::free(Chunk);
28 Chunk = nullptr;
29 StackSize = 0;
30#ifndef NDEBUG
31 ItemTypes.clear();
32#endif
33}
34
35void *InterpStack::grow(size_t Size) {
36 assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
37
38 if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
39 if (Chunk && Chunk->Next) {
40 Chunk = Chunk->Next;
41 } else {
42 StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk);
43 if (Chunk)
44 Chunk->Next = Next;
45 Chunk = Next;
46 }
47 }
48
49 auto *Object = reinterpret_cast<void *>(Chunk->End);
50 Chunk->End += Size;
51 StackSize += Size;
52 return Object;
53}
54
55void *InterpStack::peekData(size_t Size) const {
56 assert(Chunk && "Stack is empty!");
57
58 StackChunk *Ptr = Chunk;
59 while (Size > Ptr->size()) {
60 Size -= Ptr->size();
61 Ptr = Ptr->Prev;
62 assert(Ptr && "Offset too large");
63 }
64
65 return reinterpret_cast<void *>(Ptr->End - Size);
66}
67
68void InterpStack::shrink(size_t Size) {
69 assert(Chunk && "Chunk is empty!");
70
71 while (Size > Chunk->size()) {
72 Size -= Chunk->size();
73 if (Chunk->Next) {
74 std::free(Chunk->Next);
75 Chunk->Next = nullptr;
76 }
77 Chunk->End = Chunk->start();
78 Chunk = Chunk->Prev;
79 assert(Chunk && "Offset too large");
80 }
81
82 Chunk->End -= Size;
83 StackSize -= Size;
84}
85
86void InterpStack::dump() const {
87#ifndef NDEBUG
88 llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n';
89 if (ItemTypes.empty())
90 return;
91
92 size_t Index = 0;
93 size_t Offset = 0;
94
95 // The type of the item on the top of the stack is inserted to the back
96 // of the vector, so the iteration has to happen backwards.
97 for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) {
98 Offset += align(primSize(*TyIt));
99
100 llvm::errs() << Index << '/' << Offset << ": ";
101 TYPE_SWITCH(*TyIt, {
102 const T &V = peek<T>(Offset);
103 llvm::errs() << V;
104 });
105 llvm::errs() << '\n';
106
107 ++Index;
108 }
109#endif
110}
#define V(N, I)
Definition: ASTContext.h:3341
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:148
void dump() const
dump the stack contents to stderr.
Definition: InterpStack.cpp:86
void clear()
Clears the stack without calling any destructors.
Definition: InterpStack.cpp:23
size_t size() const
Returns the size of the stack in bytes.
Definition: InterpStack.h:85
~InterpStack()
Destroys the stack, freeing up storage.
Definition: InterpStack.cpp:21
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:126
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:23
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T