clang: lib/Interpreter/Value.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/raw_os_ostream.h"
21#include
22#include
23#include
24
25namespace {
26
27
28class ValueStorage {
29public:
30 using DtorFunc = void (*)(void *);
31
32 static unsigned char *CreatePayload(void *DtorF, size_t AllocSize,
33 size_t ElementsSize) {
34 if (AllocSize < sizeof(Canary))
35 AllocSize = sizeof(Canary);
36 unsigned char *Buf =
37 new unsigned char[ValueStorage::getPayloadOffset() + AllocSize];
38 ValueStorage *VS = new (Buf) ValueStorage(DtorF, AllocSize, ElementsSize);
39 std::memcpy(VS->getPayload(), Canary, sizeof(Canary));
40 return VS->getPayload();
41 }
42
43 unsigned char *getPayload() { return Storage; }
44 const unsigned char *getPayload() const { return Storage; }
45
46 static unsigned getPayloadOffset() {
47 static ValueStorage Dummy(nullptr, 0, 0);
48 return Dummy.getPayload() - reinterpret_cast<unsigned char *>(&Dummy);
49 }
50
51 static ValueStorage *getFromPayload(void *Payload) {
52 ValueStorage *R = reinterpret_cast<ValueStorage *>(
53 (unsigned char *)Payload - getPayloadOffset());
54 return R;
55 }
56
57 void Retain() { ++RefCnt; }
58
59 void Release() {
60 assert(RefCnt > 0 && "Can't release if reference count is already zero");
61 if (--RefCnt == 0) {
62
63 if (Dtor && IsAlive()) {
64 assert(Elements && "We at least should have 1 element in Value");
65 size_t Stride = AllocSize / Elements;
66 for (size_t Idx = 0; Idx < Elements; ++Idx)
67 (*Dtor)(getPayload() + Idx * Stride);
68 }
69 delete[] reinterpret_cast<unsigned char *>(this);
70 }
71 }
72
73
74
75
76 bool IsAlive() const {
77 return std::memcmp(getPayload(), Canary, sizeof(Canary)) != 0;
78 }
79
80private:
81 ValueStorage(void *DtorF, size_t AllocSize, size_t ElementsNum)
82 : RefCnt(1), Dtor(reinterpret_cast(DtorF)),
83 AllocSize(AllocSize), Elements(ElementsNum) {}
84
85 mutable unsigned RefCnt;
86 DtorFunc Dtor = nullptr;
87 size_t AllocSize = 0;
88 size_t Elements = 0;
90
91
92
93 static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,
94 0x2d, 0x23, 0x95, 0x91};
95};
96}
97
99
103
105 QT = ET->getDecl()->getIntegerType();
106
108 if (!BT || BT->isNullPtrType())
110
112 default:
113 assert(false && "Type not supported");
115#define X(type, name) \
116 case BuiltinType:📛 \
117 return Value::K_##name;
119#undef X
120 }
121}
122
132
134 void *DtorF = nullptr;
135 size_t ElementsSize = 1;
137
138 if (const auto *ArrTy =
139 llvm::dyn_cast(DtorTy.getTypePtr())) {
140 DtorTy = ArrTy->getElementType();
141 llvm::APInt ArrSize(sizeof(size_t) * 8, 1);
142 do {
143 ArrSize *= ArrTy->getSize();
144 ArrTy = llvm::dyn_cast(
145 ArrTy->getElementType().getTypePtr());
146 } while (ArrTy);
147 ElementsSize = static_cast<size_t>(ArrSize.getZExtValue());
148 }
151 llvm::dyn_cast(RT->getDecl())) {
153 Interp.CompileDtorCall(CXXRD))
154 DtorF = reinterpret_cast<void *>(Addr->getValue());
155 else
156 llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());
157 }
158 }
159
160 size_t AllocSize =
162 unsigned char *Payload =
163 ValueStorage::CreatePayload(DtorF, AllocSize, ElementsSize);
164 setPtr((void *)Payload);
165 }
166 }
167}
168
170 : Interp(RHS.Interp), OpaqueType(RHS.OpaqueType), Data(RHS.Data),
171 ValueKind(RHS.ValueKind), IsManuallyAlloc(RHS.IsManuallyAlloc) {
173 ValueStorage::getFromPayload(getPtr())->Retain();
174}
175
177 Interp = std::exchange(RHS.Interp, nullptr);
178 OpaqueType = std::exchange(RHS.OpaqueType, nullptr);
179 Data = RHS.Data;
180 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
181 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);
182
183 if (IsManuallyAlloc)
184 ValueStorage::getFromPayload(getPtr())->Release();
185}
186
189 ValueStorage::getFromPayload(getPtr())->Release();
190
196
198 ValueStorage::getFromPayload(getPtr())->Retain();
199
200 return *this;
201}
202
204 if (this != &RHS) {
205 if (IsManuallyAlloc)
206 ValueStorage::getFromPayload(getPtr())->Release();
207
208 Interp = std::exchange(RHS.Interp, nullptr);
209 OpaqueType = std::exchange(RHS.OpaqueType, nullptr);
210 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
211 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);
212
213 Data = RHS.Data;
214 }
215 return *this;
216}
217
220 ValueStorage::getFromPayload(getPtr())->Release();
225}
226
228
231 return Data.m_Ptr;
232}
233
236}
237
239 assert(Interp != nullptr &&
240 "Can't get interpreter from a default constructed value");
242}
243
245 assert(Interp != nullptr &&
246 "Can't get interpreter from a default constructed value");
248}
249
251
254}
255
257
259 Out << "Not implement yet.\n";
260}
262 Out << "Not implement yet.\n";
263}
265 assert(OpaqueType != nullptr && "Can't print default Value");
266 Out << "Not implement yet.\n";
267}
268
269}
Defines the clang::ASTContext interface.
#define REPL_BUILTIN_TYPES
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
This class is used for builtin types like 'int'.
Represents a C++ struct/union/class.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Provides top-level interfaces for incremental compilation and execution.
const ASTContext & getASTContext() const
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
static QualType getFromOpaquePtr(const void *Ptr)
QualType getCanonicalType() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
bool isConstantArrayType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
bool isMemberPointerType() const
bool isObjectType() const
Determine whether this type is an object type.
const T * getAs() const
Member-template getAs'.
bool isRecordType() const
void print(llvm::raw_ostream &Out) const
ASTContext & getASTContext()
Interpreter & getInterpreter()
void printType(llvm::raw_ostream &Out) const
Value & operator=(const Value &RHS)
void printData(llvm::raw_ostream &Out) const
The JSON file list parser is used to communicate input to InstallAPI.
static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT)